internal async Task DeleteRefByNameTest() { TreeNode tr = new TreeNode.Builder(new List <TreeTreeReference>(0), new List <TreeBlobReference>(0)); await trrepo.PersistTree(tr.ID, new IVO.Definition.Containers.ImmutableContainer <TreeID, TreeNode>(trx => trx.ID, tr)); Commit cm = new Commit.Builder(new List <CommitID>(0), tr.ID, "James S. Dunne", DateTimeOffset.Now, "Initial commit."); await cmrepo.PersistCommit(cm); Ref rf = new Ref.Builder((RefName)"v1.0", cm.ID); await rfrepo.PersistRef(rf); var edrf = await rfrepo.DeleteRefByName((RefName)"v1.0"); Assert.IsFalse(edrf.HasErrors); Ref drf = edrf.Value; Assert.IsNotNull(drf); Assert.AreEqual(rf.Name.ToString(), drf.Name.ToString()); Assert.AreEqual(rf.CommitID, drf.CommitID); var errf = await rfrepo.GetRefByName((RefName)"v1.0"); Assert.IsTrue(errf.HasErrors); Assert.AreEqual(1, errf.Errors.Count); }
internal async Task DeleteTagByNameTest() { TreeNode tr = new TreeNode.Builder(new List <TreeTreeReference>(0), new List <TreeBlobReference>(0)); await trrepo.PersistTree(tr.ID, new IVO.Definition.Containers.ImmutableContainer <TreeID, TreeNode>(trx => trx.ID, tr)); Commit cm = new Commit.Builder(new List <CommitID>(0), tr.ID, "James S. Dunne", DateTimeOffset.Now, "Initial commit."); await cmrepo.PersistCommit(cm); Tag tg = new Tag.Builder((TagName)"v1.0", cm.ID, "James S. Dunne", DateTimeOffset.Now, "Testing tags"); await tgrepo.PersistTag(tg); var retgPre = await tgrepo.GetTag(tg.ID); Assert.IsFalse(retgPre.HasErrors); Tag rtgPre = retgPre.Value; Assert.IsNotNull(rtgPre); Assert.AreEqual(tg.ID, rtgPre.ID); Assert.AreEqual(tg.Name.ToString(), rtgPre.Name.ToString()); Assert.AreEqual(tg.CommitID, rtgPre.CommitID); Assert.AreEqual(tg.Tagger, rtgPre.Tagger); Assert.AreEqual(tg.DateTagged.ToString(), rtgPre.DateTagged.ToString()); await tgrepo.DeleteTagByName((TagName)"v1.0"); var retgPost = await tgrepo.GetTag(tg.ID); Assert.IsTrue(retgPost.HasErrors); Assert.AreEqual(1, retgPost.Errors.Count); }
void TestIDGeneration() { // Create a Blob: Blob bl = new Blob.Builder( pContents: Encoding.UTF8.GetBytes("Sample README content.") ); Console.WriteLine(bl.ID.ToString()); // Create a Tree: Tree tr = new Tree.Builder( new List <TreeTreeReference>(0), new List <TreeBlobReference> { new TreeBlobReference.Builder("README", bl.ID) } ); Console.WriteLine(tr.ID.ToString()); // Create a Commit: Commit cm = new Commit.Builder( pParents: new List <CommitID>(0), pTreeID: tr.ID, pCommitter: "James Dunne <*****@*****.**>", pDateCommitted: DateTimeOffset.Now, pMessage: "A commit message here." ); Console.WriteLine(cm.ID.ToString()); }
async Task <CommitID> TestCreateCommit(TreeID treeid, int num) { var db = getDataContext(); ICommitRepository cmrepo = new CommitRepository(db); IRefRepository rfrepo = new RefRepository(db); Tuple <Ref, Commit> parent = await cmrepo.GetCommitByRef("HEAD"); Commit cm = new Commit.Builder( pParents: parent == null ? new List <CommitID>(0) : new List <CommitID>(1) { parent.Item2.ID }, pTreeID: treeid, pCommitter: "James Dunne <*****@*****.**>", pDateCommitted: DateTimeOffset.Parse("2011-08-29 00:00:00 -0500"), pMessage: "Commit #" + num.ToString() + "." ); Console.WriteLine("CommitID {0}", cm.ID); // Persist the commit: await cmrepo.PersistCommit(cm); // Once the commit is persisted, update HEAD ref: await rfrepo.PersistRef(new Ref.Builder("HEAD", cm.ID)); return(cm.ID); }
internal static Errorable <Tuple <Tag, Commit> > retrieve(ConsistencyError errorIfNotExist, SqlCommand cmd, SqlDataReader dr) { // If no result, return null: if (!dr.Read()) { return(errorIfNotExist); } TagID tgid = (TagID)dr.GetSqlBinary(0).Value; Tag.Builder tgb = new Tag.Builder( pName: (TagName)dr.GetSqlString(1).Value, pCommitID: (CommitID)dr.GetSqlBinary(2).Value, pTagger: dr.GetSqlString(3).Value, pDateTagged: dr.GetDateTimeOffset(4), pMessage: dr.GetSqlString(5).Value ); Tag tg = tgb; if (tg.ID != tgid) { return(new ComputedTagIDMismatchError(tg.ID, tgid)); } const int offs = 6; CommitID id = (CommitID)dr.GetSqlBinary(0 + offs).Value; Commit.Builder cmb = new Commit.Builder( pParents: new System.Collections.Generic.List <CommitID>(2), pTreeID: (TreeID)dr.GetSqlBinary(1 + offs).Value, pCommitter: dr.GetSqlString(2 + offs).Value, pDateCommitted: dr.GetDateTimeOffset(3 + offs), pMessage: dr.GetSqlString(4 + offs).Value ); // Read the parent commit ids from the second result: if (dr.NextResult()) { while (dr.Read()) { cmb.Parents.Add((CommitID)dr.GetSqlBinary(0).Value); } cmb.Parents.Sort(new CommitID.Comparer()); } Commit cm = cmb; if (cm.ID != id) { return(new ComputedCommitIDMismatchError(cm.ID, id)); } return(new Tuple <Tag, Commit>(tg, cm)); }
internal async Task PersistRefTest() { TreeNode tr = new TreeNode.Builder(new List <TreeTreeReference>(0), new List <TreeBlobReference>(0)); await trrepo.PersistTree(tr.ID, new IVO.Definition.Containers.ImmutableContainer <TreeID, TreeNode>(trx => trx.ID, tr)); Commit cm = new Commit.Builder(new List <CommitID>(0), tr.ID, "James S. Dunne", DateTimeOffset.Now, "Initial commit."); await cmrepo.PersistCommit(cm); Ref rf = new Ref.Builder((RefName)"v1.0", cm.ID); await rfrepo.PersistRef(rf); }
internal async Task PersistTagTest() { TreeNode tr = new TreeNode.Builder(new List <TreeTreeReference>(0), new List <TreeBlobReference>(0)); await trrepo.PersistTree(tr.ID, new IVO.Definition.Containers.ImmutableContainer <TreeID, TreeNode>(trx => trx.ID, tr)); Commit cm = new Commit.Builder(new List <CommitID>(0), tr.ID, "James S. Dunne", DateTimeOffset.Now, "Initial commit."); await cmrepo.PersistCommit(cm); Tag tg = new Tag.Builder((TagName)"v1.0", cm.ID, "James S. Dunne", DateTimeOffset.Now, "Testing tags"); await tgrepo.PersistTag(tg); }
public Errorable <Tuple <Ref, Commit> > retrieve(SqlCommand cmd, SqlDataReader dr) { // If no result, return null: if (!dr.Read()) { return(new RefNameDoesNotExistError(this._refName)); } Ref.Builder rfb = new Ref.Builder( pName: (RefName)dr.GetSqlString(0).Value, pCommitID: (CommitID)dr.GetSqlBinary(1).Value ); Ref rf = rfb; const int offs = 2; CommitID id = (CommitID)dr.GetSqlBinary(0 + offs).Value; Commit.Builder cmb = new Commit.Builder( pParents: new System.Collections.Generic.List <CommitID>(2), pTreeID: (TreeID)dr.GetSqlBinary(1 + offs).Value, pCommitter: dr.GetSqlString(2 + offs).Value, pDateCommitted: dr.GetDateTimeOffset(3 + offs), pMessage: dr.GetSqlString(4 + offs).Value ); // Read the parent commit ids from the second result: if (dr.NextResult()) { while (dr.Read()) { cmb.Parents.Add((CommitID)dr.GetSqlBinary(0).Value); } cmb.Parents.Sort(new CommitID.Comparer()); } Commit cm = cmb; if (cm.ID != id) { return(new ComputedCommitIDMismatchError(cm.ID, id)); } return(new Tuple <Ref, Commit>(rf, cm)); }
private Errorable <Commit> retrieve(SqlCommand cmd, SqlDataReader dr) { // If no result, return null: if (!dr.Read()) { return(new CommitIDRecordDoesNotExistError(this._id)); } CommitID id = (CommitID)dr.GetSqlBinary(0).Value; Commit.Builder b = new Commit.Builder( pParents: new System.Collections.Generic.List <CommitID>(10), pTreeID: (TreeID)dr.GetSqlBinary(1).Value, pCommitter: dr.GetSqlString(2).Value, pDateCommitted: dr.GetDateTimeOffset(3), pMessage: dr.GetSqlString(4).Value ); // Read the parent commit ids from the second result: if (dr.NextResult()) { while (dr.Read()) { b.Parents.Add((CommitID)dr.GetSqlBinary(0).Value); } b.Parents.Sort(new CommitID.Comparer()); } Commit cm = b; if (cm.ID != id) { throw new ComputedCommitIDMismatchError(cm.ID, id); } return(cm); }
public Errorable <CommitTree> retrieve(SqlCommand cmd, SqlDataReader dr, int expectedCount) { Dictionary <CommitID, Commit.Builder> commits = new Dictionary <CommitID, Commit.Builder>(expectedCount); CommitPartial.Builder cmPartial = null; // Iterate through rows of the recursive query, assuming ordering of rows guarantees tree depth locality. while (dr.Read()) { SqlBinary b0 = dr.GetSqlBinary(0); SqlBinary b1 = dr.GetSqlBinary(1); CommitID?cmid = b0.IsNull ? (CommitID?)null : (CommitID?)b0.Value; CommitID?parent_cmid = b1.IsNull ? (CommitID?)null : (CommitID?)b1.Value; int depth = dr.GetSqlInt32(6).Value; if (depth == this._depth) { // This should be the last record and it is partial because its parent CommitIDs are unknown: cmPartial = new CommitPartial.Builder( pID: parent_cmid.Value, pTreeID: (TreeID)dr.GetSqlBinary(2).Value, pCommitter: dr.GetSqlString(3).Value, pDateCommitted: dr.GetDateTimeOffset(4), pMessage: dr.GetSqlString(5).Value ); if (cmid.HasValue) { commits[cmid.Value].Parents.Add(parent_cmid.Value); } Debug.Assert(!dr.Read()); break; } // Create a commit builder: Commit.Builder cmb = new Commit.Builder( pParents: new List <CommitID>(2), pTreeID: (TreeID)dr.GetSqlBinary(2).Value, pCommitter: dr.GetSqlString(3).Value, pDateCommitted: dr.GetDateTimeOffset(4), pMessage: dr.GetSqlString(5).Value ); commits.Add(parent_cmid.Value, cmb); if (cmid.HasValue) { commits[cmid.Value].Parents.Add(parent_cmid.Value); } } // Finalize each commit builder: List <ICommit> finals = new List <ICommit>(commits.Count); foreach (KeyValuePair <CommitID, Commit.Builder> pair in commits) { Commit cm = pair.Value; // TODO: Would it be useful to know which CommitIDs? if (cm.ID != pair.Key) { return(new ComputedCommitIDMismatchError(cm.ID, pair.Key)); } finals.Add(cm); } if (cmPartial != null) { finals.Add((CommitPartial)cmPartial); } // Return the final result with immutable objects: return(new CommitTree(this._id, new ImmutableContainer <CommitID, ICommit>(cm => cm.ID, finals))); }
private async Task <Errorable <Commit> > getCommit(CommitID id) { FileInfo fi = system.getPathByID(id); if (!fi.Exists) { return(null); } byte[] buf; int nr = 0; using (var fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 16384, true)) { // TODO: implement an async buffered Stream: buf = new byte[16384]; nr = await fs.ReadAsync(buf, 0, 16384).ConfigureAwait(continueOnCapturedContext: false); if (nr >= 16384) { // My, what a large commit you have! throw new NotSupportedException(); } } Commit.Builder cb = new Commit.Builder() { Parents = new List <CommitID>() }; // Parse the Commit: using (var ms = new MemoryStream(buf, 0, nr, false)) using (var sr = new StreamReader(ms, Encoding.UTF8)) { string line; // Read the list of parent CommitIDs: while ((line = sr.ReadLine()) != null) { if (!line.StartsWith("parent ")) { break; } string parent_commitid = line.Substring("parent ".Length); var ecid = CommitID.TryParse(parent_commitid); if (ecid.HasErrors) { return(ecid.Errors); } cb.Parents.Add(ecid.Value); } // Set TreeID: if (line == null || !line.StartsWith("tree ")) { return(new CommitParseExpectedTreeError()); } var etrid = TreeID.TryParse(line.Substring("tree ".Length)); if (etrid.HasErrors) { return(etrid.Errors); } cb.TreeID = etrid.Value; // Set Committer: line = sr.ReadLine(); if (line == null || !line.StartsWith("committer ")) { return(new CommitParseExpectedCommitterError()); } cb.Committer = line.Substring("committer ".Length); // Set DateCommitted: line = sr.ReadLine(); if (line == null || !line.StartsWith("date ")) { return(new CommitParseExpectedDateError()); } // NOTE: date parsing will result in an inexact DateTimeOffset from what was created with, but it // is close enough because the SHA-1 hash is calculated using the DateTimeOffset.ToString(), so // only the ToString() representations of the DateTimeOffsets need to match. DateTimeOffset tmpDate; if (!DateTimeOffset.TryParse(line.Substring("date ".Length), out tmpDate)) { return(new CommitParseBadDateFormatError()); } cb.DateCommitted = tmpDate; // Skip empty line: line = sr.ReadLine(); if (line == null || line.Length != 0) { return(new CommitParseExpectedBlankLineError()); } // Set Message: cb.Message = sr.ReadToEnd(); } // Create the immutable Commit from the Builder: Commit cm = cb; // Validate the computed CommitID: if (cm.ID != id) { return(new ComputedCommitIDMismatchError(cm.ID, id)); } return(cm); }
async Task DemonstrateHashing() { var db = getDataContext(); IBlobRepository blrepo = new BlobRepository(db); ITreeRepository trrepo = new TreeRepository(db); ICommitRepository cmrepo = new CommitRepository(db); IRefRepository rfrepo = new RefRepository(db); // Create a sample set of blobs: Blob readmeBlob; ImmutableContainer <BlobID, Blob> blobs = new ImmutableContainer <BlobID, Blob>( bl => bl.ID, readmeBlob = new Blob.Builder(pContents: Encoding.UTF8.GetBytes(@"Hello world")) ); Console.Out.WriteAsync(String.Format("Blob {0} = \"{1}\"" + Environment.NewLine, readmeBlob.ID.ToString(firstLength: 7), Encoding.UTF8.GetString(readmeBlob.Contents))); // Persist them: var persistingBlobs = blrepo.PersistBlobs(blobs); // Create an initial tree: Tree trRoot; ImmutableContainer <TreeID, Tree> trees = new ImmutableContainer <TreeID, Tree>( tr => tr.ID, new Tree[] { trRoot = new Tree.Builder( pTrees: new List <TreeTreeReference>(0), pBlobs: new List <TreeBlobReference> { new TreeBlobReference.Builder(pName: "README", pBlobID: readmeBlob.ID) } ) } ); // Dump the tree: RecursivePrint(trRoot.ID, trees); // Now wait for the blob persistence to complete: await persistingBlobs; // Persist our tree now: var persistTrees = trrepo.PersistTree(trRoot.ID, trees); await persistTrees; // Let's make a commit out of all that: Commit cm1 = new Commit.Builder( pParents: new List <CommitID>(0), pTreeID: trRoot.ID, pCommitter: @"James Dunne <*****@*****.**>", pDateCommitted: DateTimeOffset.Now, pMessage: "Initial commit." ); // Persist that commit: Console.Out.WriteAsync(String.Format("Persisting commit {0}..." + Environment.NewLine, cm1.ID.ToString(firstLength: 7))); await cmrepo.PersistCommit(cm1); // Let's create a ref to point to it: await rfrepo.DestroyRefByName("demo/HEAD"); await rfrepo.PersistRef(new Ref.Builder(pName: "demo/HEAD", pCommitID: cm1.ID)); await Console.Out.WriteAsync(String.Format("Pointed demo/HEAD to commit {0}" + Environment.NewLine, cm1.ID.ToString(firstLength: 7))); // Now let's create a new blob with some revised contents: (adding a period at the end) Blob readmeBlob2; blobs = new ImmutableContainer <BlobID, Blob>( bl => bl.ID, readmeBlob2 = new Blob.Builder(Encoding.UTF8.GetBytes(@"Hello world.")) ); var persistBlobs2 = blrepo.PersistBlobs(blobs); // Make a new tree out of the old tree: Tree.Builder trRoot2b = new Tree.Builder(trRoot); // Point README to the new BlobID: trRoot2b.Blobs[0] = new TreeBlobReference.Builder(trRoot2b.Blobs[0]) { BlobID = readmeBlob2.ID }; // Freeze our Tree.Builder to a Tree: Tree trRoot2; trees = new ImmutableContainer <TreeID, Tree>(tr => tr.ID, trRoot2 = trRoot2b); // Wait for the blobs to persist: await persistBlobs2; // Now persist the new tree: await trrepo.PersistTree(trRoot2.ID, trees); // Load a streamed blob: IStreamedBlob strbl = await blrepo.GetStreamedBlob(readmeBlob.ID); await strbl.ReadStream(blsr => { Console.WriteLine("blob is {0} length", blsr.Length); byte[] dum = new byte[8040]; int count = 8040; try { while ((count = blsr.Read(dum, 0, 8040)) > 0) { for (int i = 0; i < (count / 40) + ((count % 40) > 0 ? 1 : 0); ++i) { Console.WriteLine(dum.ToHexString(i * 40, Math.Min(count - (i * 40), 40))); } } } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); } }); }