/// <exception cref="NGit.Errors.CorruptObjectException"></exception> /// <exception cref="System.IO.IOException"></exception> private bool IsModified(string path) { NameConflictTreeWalk tw = new NameConflictTreeWalk(repo); tw.AddTree(new DirCacheIterator(dc)); tw.AddTree(new FileTreeIterator(repo)); tw.Recursive = true; tw.Filter = PathFilter.Create(path); DirCacheIterator dcIt; WorkingTreeIterator wtIt; while (tw.Next()) { dcIt = tw.GetTree <DirCacheIterator>(0); wtIt = tw.GetTree <WorkingTreeIterator>(1); if (dcIt == null || wtIt == null) { return(true); } if (wtIt.IsModified(dcIt.GetDirCacheEntry(), true)) { return(true); } } return(false); }
/// <summary>Scan index and merge tree (no HEAD).</summary> /// <remarks> /// Scan index and merge tree (no HEAD). Used e.g. for initial checkout when /// there is no head yet. /// </remarks> /// <exception cref="NGit.Errors.MissingObjectException">NGit.Errors.MissingObjectException /// </exception> /// <exception cref="NGit.Errors.IncorrectObjectTypeException">NGit.Errors.IncorrectObjectTypeException /// </exception> /// <exception cref="NGit.Errors.CorruptObjectException">NGit.Errors.CorruptObjectException /// </exception> /// <exception cref="System.IO.IOException">System.IO.IOException</exception> public virtual void PrescanOneTree() { removed.Clear(); updated.Clear(); conflicts.Clear(); builder = dc.Builder(); walk = new NameConflictTreeWalk(repo); walk.AddTree(mergeCommitTree); walk.AddTree(new DirCacheBuildIterator(builder)); walk.AddTree(workingTree); while (walk.Next()) { ProcessEntry(walk.GetTree <CanonicalTreeParser>(0), walk.GetTree <DirCacheBuildIterator >(1), walk.GetTree <WorkingTreeIterator>(2)); if (walk.IsSubtree) { walk.EnterSubtree(); } } conflicts.RemoveAll(removed); }
private AbstractTreeIterator GetTree(int tree) { return(tw.GetTree <AbstractTreeIterator>(tree)); }
/// <exception cref="System.IO.IOException"></exception> protected internal override bool MergeImpl() { bool implicitDirCache = false; if (dircache == null) { dircache = GetRepository().LockDirCache(); implicitDirCache = true; } try { builder = dircache.Builder(); DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder); tw = new NameConflictTreeWalk(db); tw.AddTree(MergeBase()); tw.AddTree(sourceTrees[0]); tw.AddTree(sourceTrees[1]); tw.AddTree(buildIt); if (workingTreeIterator != null) { tw.AddTree(workingTreeIterator); } while (tw.Next()) { if (!ProcessEntry(tw.GetTree <CanonicalTreeParser>(T_BASE), tw.GetTree <CanonicalTreeParser >(T_OURS), tw.GetTree <CanonicalTreeParser>(T_THEIRS), tw.GetTree <DirCacheBuildIterator >(T_INDEX), (workingTreeIterator == null) ? null : tw.GetTree <WorkingTreeIterator >(T_FILE))) { CleanUp(); return(false); } if (tw.IsSubtree && enterSubtree) { tw.EnterSubtree(); } } if (!inCore) { // All content-merges are successfully done. If we can now write the // new index we are on quite safe ground. Even if the checkout of // files coming from "theirs" fails the user can work around such // failures by checking out the index again. if (!builder.Commit()) { CleanUp(); throw new IndexWriteException(); } builder = null; // No problem found. The only thing left to be done is to checkout // all files from "theirs" which have been selected to go into the // new index. Checkout(); } else { builder.Finish(); builder = null; } if (GetUnmergedPaths().IsEmpty()) { resultTree = dircache.WriteTree(oi); return(true); } else { resultTree = null; return(false); } } finally { if (implicitDirCache) { dircache.Unlock(); } } }
/// <exception cref="System.InvalidOperationException"></exception> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.Exception"></exception> public virtual void TestIterator() { TreeSet <long> modTimes = new TreeSet <long>(); FilePath lastFile = null; for (int i = 0; i < 10; i++) { lastFile = new FilePath(db.WorkTree, "0." + i); FileUtils.CreateNewFile(lastFile); if (i == 5) { FsTick(lastFile); } } modTimes.AddItem(FsTick(lastFile)); for (int i_1 = 0; i_1 < 10; i_1++) { lastFile = new FilePath(db.WorkTree, "1." + i_1); FileUtils.CreateNewFile(lastFile); } modTimes.AddItem(FsTick(lastFile)); for (int i_2 = 0; i_2 < 10; i_2++) { lastFile = new FilePath(db.WorkTree, "2." + i_2); FileUtils.CreateNewFile(lastFile); if (i_2 % 4 == 0) { FsTick(lastFile); } } FileTreeIteratorWithTimeControl fileIt = new FileTreeIteratorWithTimeControl(db, modTimes); NameConflictTreeWalk tw = new NameConflictTreeWalk(db); tw.AddTree(fileIt); tw.Recursive = true; FileTreeIterator t; long t0 = 0; for (int i_3 = 0; i_3 < 10; i_3++) { NUnit.Framework.Assert.IsTrue(tw.Next()); t = tw.GetTree <FileTreeIterator>(0); if (i_3 == 0) { t0 = t.GetEntryLastModified(); } else { NUnit.Framework.Assert.AreEqual(t0, t.GetEntryLastModified()); } } long t1 = 0; for (int i_4 = 0; i_4 < 10; i_4++) { NUnit.Framework.Assert.IsTrue(tw.Next()); t = tw.GetTree <FileTreeIterator>(0); if (i_4 == 0) { t1 = t.GetEntryLastModified(); NUnit.Framework.Assert.IsTrue(t1 > t0); } else { NUnit.Framework.Assert.AreEqual(t1, t.GetEntryLastModified()); } } long t2 = 0; for (int i_5 = 0; i_5 < 10; i_5++) { NUnit.Framework.Assert.IsTrue(tw.Next()); t = tw.GetTree <FileTreeIterator>(0); if (i_5 == 0) { t2 = t.GetEntryLastModified(); NUnit.Framework.Assert.IsTrue(t2 > t1); } else { NUnit.Framework.Assert.AreEqual(t2, t.GetEntryLastModified()); } } }
public static void MergeTest(EngineContext engineContext) { // TODO: Currently hardcoded var db = new FileRepository(new FilePath(@"C:\DEV\hotei_scene", Constants.DOT_GIT)); var git = new Git(db); var tree1Ref = db.GetRef("test"); var tree2Ref = db.GetRef(Constants.HEAD); var tree1CommitId = tree1Ref.GetObjectId(); var tree2CommitId = tree2Ref.GetObjectId(); // Merge tree1 into current tree var mergeResult = git.Merge().Include(tree1CommitId).Call(); if (mergeResult.GetMergeStatus() == MergeStatus.CONFLICTING) { foreach (var conflict in mergeResult.GetConflicts()) { if (conflict.Key.EndsWith(".hotei")) { // Search base tree (common ancestor), if any var walk = new RevWalk(db); walk.SetRevFilter(RevFilter.MERGE_BASE); walk.MarkStart(walk.ParseCommit(tree1CommitId)); walk.MarkStart(walk.ParseCommit(tree2CommitId)); var baseTree = walk.Next(); var tw = new NameConflictTreeWalk(db); tw.AddTree(new RevWalk(db).ParseTree(tree1CommitId).ToObjectId()); tw.AddTree(new RevWalk(db).ParseTree(tree2CommitId).ToObjectId()); if (baseTree != null) { tw.AddTree(new RevWalk(db).ParseTree(baseTree.ToObjectId()).ToObjectId()); } tw.Filter = PathFilter.Create(conflict.Key); // Should be only one iteration while (tw.Next()) { var tree0 = baseTree != null?tw.GetTree <AbstractTreeIterator>(2) : null; var tree1 = tw.GetTree <AbstractTreeIterator>(0); var tree2 = tw.GetTree <AbstractTreeIterator>(1); // Get contents of every versions for the 3-way merge var data0 = baseTree != null?LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree0.EntryObjectId).GetBytes())) : null; var data1 = LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree1.EntryObjectId).GetBytes())); var data2 = LoadEntities(new MemoryStream(tw.ObjectReader.Open(tree2.EntryObjectId).GetBytes())); // Perform 3-way merge var entities = new List <EntityDefinition>(); ThreeWayMergeOrdered.Merge(entities, data0, data1, data2, x => x.Guid, (x, y) => x == y, ResolveEntityConflicts); // Save new merged file var fileStream = new FileStream(new FilePath(db.WorkTree, conflict.Key), FileMode.Create, FileAccess.Write); var stream = new BinarySerializationWriter(fileStream); stream.Context.Serializer = Serializer; stream.SerializeClass(null, ref entities, ArchiveMode.Serialize); fileStream.Close(); // TODO: Check if all conflicts are really resolved // Add resolved file for merge commit git.Add().AddFilepattern(conflict.Key).Call(); } } } } }