Example #1
0
        ObjectId WriteWorkingDirectoryTree(RevTree headTree, DirCache index)
        {
            DirCache        dc = DirCache.NewInCore();
            DirCacheBuilder cb = dc.Builder();

            ObjectInserter oi = _repo.NewObjectInserter();

            try {
                TreeWalk tw = new TreeWalk(_repo);
                tw.Reset();
                tw.AddTree(new FileTreeIterator(_repo));
                tw.AddTree(headTree);
                tw.AddTree(new DirCacheIterator(index));

                while (tw.Next())
                {
                    // Ignore untracked files
                    if (tw.IsSubtree)
                    {
                        tw.EnterSubtree();
                    }
                    else if (tw.GetFileMode(0) != NGit.FileMode.MISSING && (tw.GetFileMode(1) != NGit.FileMode.MISSING || tw.GetFileMode(2) != NGit.FileMode.MISSING))
                    {
                        WorkingTreeIterator f            = tw.GetTree <WorkingTreeIterator>(0);
                        DirCacheIterator    dcIter       = tw.GetTree <DirCacheIterator>(2);
                        DirCacheEntry       currentEntry = dcIter.GetDirCacheEntry();
                        DirCacheEntry       ce           = new DirCacheEntry(tw.PathString);
                        if (!f.IsModified(currentEntry, true))
                        {
                            ce.SetLength(currentEntry.Length);
                            ce.LastModified = currentEntry.LastModified;
                            ce.FileMode     = currentEntry.FileMode;
                            ce.SetObjectId(currentEntry.GetObjectId());
                        }
                        else
                        {
                            long sz = f.GetEntryLength();
                            ce.SetLength(sz);
                            ce.LastModified = f.GetEntryLastModified();
                            ce.FileMode     = f.EntryFileMode;
                            var data = f.OpenEntryStream();
                            try {
                                ce.SetObjectId(oi.Insert(Constants.OBJ_BLOB, sz, data));
                            } finally {
                                data.Close();
                            }
                        }
                        cb.Add(ce);
                    }
                }

                cb.Finish();
                return(dc.WriteTree(oi));
            } finally {
                oi.Release();
            }
        }
Example #2
0
        public Stash Create(string message)
        {
            UserConfig config = _repo.GetConfig().Get(UserConfig.KEY);
            RevWalk    rw     = new RevWalk(_repo);
            ObjectId   headId = _repo.Resolve(Constants.HEAD);
            var        parent = rw.ParseCommit(headId);

            PersonIdent author = new PersonIdent(config.GetAuthorName() ?? "unknown", config.GetAuthorEmail() ?? "unknown@(none).");

            if (string.IsNullOrEmpty(message))
            {
                // Use the commit summary as message
                message = parent.Abbreviate(7).ToString() + " " + parent.GetShortMessage();
                int i = message.IndexOfAny(new char[] { '\r', '\n' });
                if (i != -1)
                {
                    message = message.Substring(0, i);
                }
            }

            // Create the index tree commit
            ObjectInserter inserter = _repo.NewObjectInserter();
            DirCache       dc       = _repo.ReadDirCache();
            var            tree_id  = dc.WriteTree(inserter);

            inserter.Release();

            string   commitMsg   = "index on " + _repo.GetBranch() + ": " + message;
            ObjectId indexCommit = GitUtil.CreateCommit(_repo, commitMsg + "\n", new ObjectId[] { headId }, tree_id, author, author);

            // Create the working dir commit
            tree_id   = WriteWorkingDirectoryTree(parent.Tree, dc);
            commitMsg = "WIP on " + _repo.GetBranch() + ": " + message;
            var wipCommit = GitUtil.CreateCommit(_repo, commitMsg + "\n", new ObjectId[] { headId, indexCommit }, tree_id, author, author);

            string   prevCommit = null;
            FileInfo sf         = StashRefFile;

            if (sf.Exists)
            {
                prevCommit = File.ReadAllText(sf.FullName).Trim(' ', '\t', '\r', '\n');
            }

            Stash s = new Stash(prevCommit, wipCommit.Name, author, commitMsg);

            FileInfo stashLog = StashLogFile;

            File.AppendAllText(stashLog.FullName, s.FullLine + "\n");
            File.WriteAllText(sf.FullName, s.CommitId + "\n");

            // Wipe all local changes
            GitUtil.HardReset(_repo, Constants.HEAD);

            s.StashCollection = this;
            return(s);
        }
        public virtual void TestRecursiveFiltering()
        {
            ObjectInserter odi  = db.NewObjectInserter();
            ObjectId       aSth = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString(
                                                 "a.sth"));
            ObjectId aTxt = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString(
                                           "a.txt"));
            ObjectId bSth = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString(
                                           "b.sth"));
            ObjectId bTxt = odi.Insert(Constants.OBJ_BLOB, Sharpen.Runtime.GetBytesForString(
                                           "b.txt"));
            DirCache        dc        = db.ReadDirCache();
            DirCacheBuilder builder   = dc.Builder();
            DirCacheEntry   aSthEntry = new DirCacheEntry("a.sth");

            aSthEntry.FileMode = FileMode.REGULAR_FILE;
            aSthEntry.SetObjectId(aSth);
            DirCacheEntry aTxtEntry = new DirCacheEntry("a.txt");

            aTxtEntry.FileMode = FileMode.REGULAR_FILE;
            aTxtEntry.SetObjectId(aTxt);
            builder.Add(aSthEntry);
            builder.Add(aTxtEntry);
            DirCacheEntry bSthEntry = new DirCacheEntry("sub/b.sth");

            bSthEntry.FileMode = FileMode.REGULAR_FILE;
            bSthEntry.SetObjectId(bSth);
            DirCacheEntry bTxtEntry = new DirCacheEntry("sub/b.txt");

            bTxtEntry.FileMode = FileMode.REGULAR_FILE;
            bTxtEntry.SetObjectId(bTxt);
            builder.Add(bSthEntry);
            builder.Add(bTxtEntry);
            builder.Finish();
            ObjectId treeId = dc.WriteTree(odi);

            odi.Flush();
            TreeWalk tw = new TreeWalk(db);

            tw.Recursive = true;
            tw.Filter    = PathSuffixFilter.Create(".txt");
            tw.AddTree(treeId);
            IList <string> paths = new List <string>();

            while (tw.Next())
            {
                paths.AddItem(tw.PathString);
            }
            IList <string> expected = new List <string>();

            expected.AddItem("a.txt");
            expected.AddItem("sub/b.txt");
            NUnit.Framework.Assert.AreEqual(expected, paths);
        }
Example #4
0
        /// <exception cref="System.Exception"></exception>
        private ObjectId Commit(ObjectInserter odi, DirCache treeB, ObjectId[] parentIds)
        {
            NGit.CommitBuilder c = new NGit.CommitBuilder();
            c.TreeId    = treeB.WriteTree(odi);
            c.Author    = new PersonIdent("A U Thor", "a.u.thor", 1L, 0);
            c.Committer = c.Author;
            c.SetParentIds(parentIds);
            c.Message = "Tree " + c.TreeId.Name;
            ObjectId id = odi.Insert(c);

            odi.Flush();
            return(id);
        }
Example #5
0
        /// <exception cref="System.IO.IOException"></exception>
        private ObjectId BuildTree(Dictionary <string, string> headEntries)
        {
            DirCache lockDirCache = DirCache.NewInCore();
            // assertTrue(lockDirCache.lock());
            DirCacheEditor editor = lockDirCache.Editor();

            if (headEntries != null)
            {
                foreach (KeyValuePair <string, string> e in headEntries.EntrySet())
                {
                    DirCacheCheckoutTest.AddEdit addEdit = new DirCacheCheckoutTest.AddEdit(e.Key, GenSha1
                                                                                                (e.Value), e.Value.Length);
                    editor.Add(addEdit);
                }
            }
            editor.Finish();
            return(lockDirCache.WriteTree(db.NewObjectInserter()));
        }
            /// <exception cref="System.IO.IOException"></exception>
            protected internal override bool MergeImpl()
            {
                tw.AddTree(MergeBase());
                tw.AddTree(sourceTrees[0]);
                tw.AddTree(sourceTrees[1]);
                bool hasConflict = false;

                builder = cache.Builder();
                while (tw.Next())
                {
                    int modeO = tw.GetRawMode(T_OURS);
                    int modeT = tw.GetRawMode(T_THEIRS);
                    if (modeO == modeT && tw.IdEqual(T_OURS, T_THEIRS))
                    {
                        Add(T_OURS, DirCacheEntry.STAGE_0);
                        continue;
                    }
                    int modeB = tw.GetRawMode(T_BASE);
                    if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
                    {
                        Add(T_THEIRS, DirCacheEntry.STAGE_0);
                    }
                    else
                    {
                        if (modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
                        {
                            Add(T_OURS, DirCacheEntry.STAGE_0);
                        }
                        else
                        {
                            if (NonTree(modeB))
                            {
                                Add(T_BASE, DirCacheEntry.STAGE_1);
                                hasConflict = true;
                            }
                            if (NonTree(modeO))
                            {
                                Add(T_OURS, DirCacheEntry.STAGE_2);
                                hasConflict = true;
                            }
                            if (NonTree(modeT))
                            {
                                Add(T_THEIRS, DirCacheEntry.STAGE_3);
                                hasConflict = true;
                            }
                            if (tw.IsSubtree)
                            {
                                tw.EnterSubtree();
                            }
                        }
                    }
                }
                builder.Finish();
                builder = null;
                if (hasConflict)
                {
                    return(false);
                }
                try
                {
                    ObjectInserter odi = GetObjectInserter();
                    resultTree = cache.WriteTree(odi);
                    odi.Flush();
                    return(true);
                }
                catch (UnmergedPathException)
                {
                    resultTree = null;
                    return(false);
                }
            }
Example #7
0
        /// <summary>
        /// Executes the
        /// <code>commit</code>
        /// command with all the options and parameters
        /// collected by the setter methods of this class. Each instance of this
        /// class should only be used for one invocation of the command (means: one
        /// call to
        /// <see cref="Call()">Call()</see>
        /// )
        /// </summary>
        /// <returns>
        /// a
        /// <see cref="NGit.Revwalk.RevCommit">NGit.Revwalk.RevCommit</see>
        /// object representing the successful commit.
        /// </returns>
        /// <exception cref="NGit.Api.Errors.NoHeadException">when called on a git repo without a HEAD reference
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.NoMessageException">when called without specifying a commit message
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.UnmergedPathsException">when the current index contained unmerged paths (conflicts)
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.ConcurrentRefUpdateException">
        /// when HEAD or branch ref is updated concurrently by someone
        /// else
        /// </exception>
        /// <exception cref="NGit.Api.Errors.WrongRepositoryStateException">when repository is not in the right state for committing
        ///     </exception>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        public override RevCommit Call()
        {
            CheckCallable();
            RepositoryState state = repo.GetRepositoryState();

            if (!state.CanCommit())
            {
                throw new WrongRepositoryStateException(MessageFormat.Format(JGitText.Get().cannotCommitOnARepoWithState
                                                                             , state.Name()));
            }
            ProcessOptions(state);
            try
            {
                if (all && !repo.IsBare && repo.WorkTree != null)
                {
                    Git git = new Git(repo);
                    try
                    {
                        git.Add().AddFilepattern(".").SetUpdate(true).Call();
                    }
                    catch (NoFilepatternException e)
                    {
                        // should really not happen
                        throw new JGitInternalException(e.Message, e);
                    }
                }
                Ref head = repo.GetRef(Constants.HEAD);
                if (head == null)
                {
                    throw new NoHeadException(JGitText.Get().commitOnRepoWithoutHEADCurrentlyNotSupported
                                              );
                }
                // determine the current HEAD and the commit it is referring to
                ObjectId headId = repo.Resolve(Constants.HEAD + "^{commit}");
                if (headId == null && amend)
                {
                    throw new WrongRepositoryStateException(JGitText.Get().commitAmendOnInitialNotPossible
                                                            );
                }
                if (headId != null)
                {
                    if (amend)
                    {
                        RevCommit   previousCommit = new RevWalk(repo).ParseCommit(headId);
                        RevCommit[] p = previousCommit.Parents;
                        for (int i = 0; i < p.Length; i++)
                        {
                            parents.Add(0, p[i].Id);
                        }
                        if (author == null)
                        {
                            author = previousCommit.GetAuthorIdent();
                        }
                    }
                    else
                    {
                        parents.Add(0, headId);
                    }
                }
                // lock the index
                DirCache index = repo.LockDirCache();
                try
                {
                    if (!only.IsEmpty())
                    {
                        index = CreateTemporaryIndex(headId, index);
                    }
                    ObjectInserter odi = repo.NewObjectInserter();
                    try
                    {
                        // Write the index as tree to the object database. This may
                        // fail for example when the index contains unmerged paths
                        // (unresolved conflicts)
                        ObjectId indexTreeId = index.WriteTree(odi);
                        if (insertChangeId)
                        {
                            InsertChangeId(indexTreeId);
                        }
                        // Create a Commit object, populate it and write it
                        NGit.CommitBuilder commit = new NGit.CommitBuilder();
                        commit.Committer = committer;
                        commit.Author    = author;
                        commit.Message   = message;
                        commit.SetParentIds(parents);
                        commit.TreeId = indexTreeId;
                        ObjectId commitId = odi.Insert(commit);
                        odi.Flush();
                        RevWalk revWalk = new RevWalk(repo);
                        try
                        {
                            RevCommit revCommit = revWalk.ParseCommit(commitId);
                            RefUpdate ru        = repo.UpdateRef(Constants.HEAD);
                            ru.SetNewObjectId(commitId);
                            if (reflogComment != null)
                            {
                                ru.SetRefLogMessage(reflogComment, false);
                            }
                            else
                            {
                                string prefix = amend ? "commit (amend): " : "commit: ";
                                ru.SetRefLogMessage(prefix + revCommit.GetShortMessage(), false);
                            }
                            if (headId != null)
                            {
                                ru.SetExpectedOldObjectId(headId);
                            }
                            else
                            {
                                ru.SetExpectedOldObjectId(ObjectId.ZeroId);
                            }
                            RefUpdate.Result rc = ru.ForceUpdate();
                            switch (rc)
                            {
                            case RefUpdate.Result.NEW:
                            case RefUpdate.Result.FORCED:
                            case RefUpdate.Result.FAST_FORWARD:
                            {
                                SetCallable(false);
                                if (state == RepositoryState.MERGING_RESOLVED)
                                {
                                    // Commit was successful. Now delete the files
                                    // used for merge commits
                                    repo.WriteMergeCommitMsg(null);
                                    repo.WriteMergeHeads(null);
                                }
                                else
                                {
                                    if (state == RepositoryState.CHERRY_PICKING_RESOLVED)
                                    {
                                        repo.WriteMergeCommitMsg(null);
                                        repo.WriteCherryPickHead(null);
                                    }
                                }
                                return(revCommit);
                            }

                            case RefUpdate.Result.REJECTED:
                            case RefUpdate.Result.LOCK_FAILURE:
                            {
                                throw new ConcurrentRefUpdateException(JGitText.Get().couldNotLockHEAD, ru.GetRef
                                                                           (), rc);
                            }

                            default:
                            {
                                throw new JGitInternalException(MessageFormat.Format(JGitText.Get().updatingRefFailed
                                                                                     , Constants.HEAD, commitId.ToString(), rc));
                            }
                            }
                        }
                        finally
                        {
                            revWalk.Release();
                        }
                    }
                    finally
                    {
                        odi.Release();
                    }
                }
                finally
                {
                    index.Unlock();
                }
            }
            catch (UnmergedPathException e)
            {
                throw new UnmergedPathsException(e);
            }
            catch (IOException e)
            {
                throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfCommitCommand
                                                , e);
            }
        }
Example #8
0
        /// <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();
                }
            }
        }
Example #9
0
		/// <exception cref="System.Exception"></exception>
		private ObjectId Commit(ObjectInserter odi, DirCache treeB, ObjectId[] parentIds)
		{
			NGit.CommitBuilder c = new NGit.CommitBuilder();
			c.TreeId = treeB.WriteTree(odi);
			c.Author = new PersonIdent("A U Thor", "a.u.thor", 1L, 0);
			c.Committer = c.Author;
			c.SetParentIds(parentIds);
			c.Message = "Tree " + c.TreeId.Name;
			ObjectId id = odi.Insert(c);
			odi.Flush();
			return id;
		}
Example #10
0
        /// <summary>
        /// Stash the contents on the working directory and index in separate commits
        /// and reset to the current HEAD commit.
        /// </summary>
        /// <remarks>
        /// Stash the contents on the working directory and index in separate commits
        /// and reset to the current HEAD commit.
        /// </remarks>
        /// <returns>stashed commit or null if no changes to stash</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException
        ///     </exception>
        public override RevCommit Call()
        {
            CheckCallable();
            Ref          head   = GetHead();
            ObjectReader reader = repo.NewObjectReader();

            try
            {
                RevCommit      headCommit = ParseCommit(reader, head.GetObjectId());
                DirCache       cache      = repo.LockDirCache();
                ObjectInserter inserter   = repo.NewObjectInserter();
                ObjectId       commitId;
                try
                {
                    TreeWalk treeWalk = new TreeWalk(reader);
                    treeWalk.Recursive = true;
                    treeWalk.AddTree(headCommit.Tree);
                    treeWalk.AddTree(new DirCacheIterator(cache));
                    treeWalk.AddTree(new FileTreeIterator(repo));
                    treeWalk.Filter = AndTreeFilter.Create(new SkipWorkTreeFilter(1), new IndexDiffFilter
                                                               (1, 2));
                    // Return null if no local changes to stash
                    if (!treeWalk.Next())
                    {
                        return(null);
                    }
                    MutableObjectId id = new MutableObjectId();
                    IList <DirCacheEditor.PathEdit> wtEdits = new AList <DirCacheEditor.PathEdit>();
                    IList <string> wtDeletes = new AList <string>();
                    do
                    {
                        AbstractTreeIterator headIter  = treeWalk.GetTree <AbstractTreeIterator>(0);
                        DirCacheIterator     indexIter = treeWalk.GetTree <DirCacheIterator>(1);
                        WorkingTreeIterator  wtIter    = treeWalk.GetTree <WorkingTreeIterator>(2);
                        if (headIter != null && indexIter != null && wtIter != null)
                        {
                            if (!indexIter.GetDirCacheEntry().IsMerged())
                            {
                                throw new UnmergedPathsException(new UnmergedPathException(indexIter.GetDirCacheEntry
                                                                                               ()));
                            }
                            if (wtIter.IdEqual(indexIter) || wtIter.IdEqual(headIter))
                            {
                                continue;
                            }
                            treeWalk.GetObjectId(id, 0);
                            DirCacheEntry entry = new DirCacheEntry(treeWalk.RawPath);
                            entry.SetLength(wtIter.GetEntryLength());
                            entry.LastModified = wtIter.GetEntryLastModified();
                            entry.FileMode     = wtIter.EntryFileMode;
                            long        contentLength = wtIter.GetEntryContentLength();
                            InputStream @in           = wtIter.OpenEntryStream();
                            try
                            {
                                entry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentLength, @in));
                            }
                            finally
                            {
                                @in.Close();
                            }
                            wtEdits.AddItem(new _PathEdit_273(entry, entry));
                        }
                        else
                        {
                            if (indexIter == null)
                            {
                                wtDeletes.AddItem(treeWalk.PathString);
                            }
                            else
                            {
                                if (wtIter == null && headIter != null)
                                {
                                    wtDeletes.AddItem(treeWalk.PathString);
                                }
                            }
                        }
                    }while (treeWalk.Next());
                    string branch = Repository.ShortenRefName(head.GetTarget().GetName());
                    // Commit index changes
                    NGit.CommitBuilder builder = CreateBuilder(headCommit);
                    builder.TreeId  = cache.WriteTree(inserter);
                    builder.Message = MessageFormat.Format(indexMessage, branch, headCommit.Abbreviate
                                                               (7).Name, headCommit.GetShortMessage());
                    ObjectId indexCommit = inserter.Insert(builder);
                    // Commit working tree changes
                    if (!wtEdits.IsEmpty() || !wtDeletes.IsEmpty())
                    {
                        DirCacheEditor editor = cache.Editor();
                        foreach (DirCacheEditor.PathEdit edit in wtEdits)
                        {
                            editor.Add(edit);
                        }
                        foreach (string path in wtDeletes)
                        {
                            editor.Add(new DirCacheEditor.DeletePath(path));
                        }
                        editor.Finish();
                    }
                    builder.AddParentId(indexCommit);
                    builder.Message = MessageFormat.Format(workingDirectoryMessage, branch, headCommit
                                                           .Abbreviate(7).Name, headCommit.GetShortMessage());
                    builder.TreeId = cache.WriteTree(inserter);
                    commitId       = inserter.Insert(builder);
                    inserter.Flush();
                    UpdateStashRef(commitId, builder.Author, builder.Message);
                }
                finally
                {
                    inserter.Release();
                    cache.Unlock();
                }
                // Hard reset to HEAD
                new ResetCommand(repo).SetMode(ResetCommand.ResetType.HARD).Call();
                // Return stashed commit
                return(ParseCommit(reader, commitId));
            }
            catch (IOException e)
            {
                throw new JGitInternalException(JGitText.Get().stashFailed, e);
            }
            finally
            {
                reader.Release();
            }
        }
Example #11
0
        public virtual void TestFindObjects()
        {
            DirCache        tree0 = DirCache.NewInCore();
            DirCacheBuilder b0    = tree0.Builder();
            ObjectReader    or    = db.NewObjectReader();
            ObjectInserter  oi    = db.NewObjectInserter();
            DirCacheEntry   aDotB = MakeEntry("a.b", EXECUTABLE_FILE);

            b0.Add(aDotB);
            DirCacheEntry aSlashB = MakeEntry("a/b", REGULAR_FILE);

            b0.Add(aSlashB);
            DirCacheEntry aSlashCSlashD = MakeEntry("a/c/d", REGULAR_FILE);

            b0.Add(aSlashCSlashD);
            DirCacheEntry aZeroB = MakeEntry("a0b", SYMLINK);

            b0.Add(aZeroB);
            b0.Finish();
            NUnit.Framework.Assert.AreEqual(4, tree0.GetEntryCount());
            ObjectId tree = tree0.WriteTree(oi);
            // Find the directories that were implicitly created above.
            TreeWalk tw = new TreeWalk(or);

            tw.AddTree(tree);
            ObjectId a       = null;
            ObjectId aSlashC = null;

            while (tw.Next())
            {
                if (tw.PathString.Equals("a"))
                {
                    a = tw.GetObjectId(0);
                    tw.EnterSubtree();
                    while (tw.Next())
                    {
                        if (tw.PathString.Equals("a/c"))
                        {
                            aSlashC = tw.GetObjectId(0);
                            break;
                        }
                    }
                    break;
                }
            }
            NUnit.Framework.Assert.AreEqual(a, TreeWalk.ForPath(or, "a", tree).GetObjectId(0)
                                            );
            NUnit.Framework.Assert.AreEqual(a, TreeWalk.ForPath(or, "a/", tree).GetObjectId(0
                                                                                            ));
            NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a", tree));
            NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a/", tree));
            NUnit.Framework.Assert.AreEqual(aDotB.GetObjectId(), TreeWalk.ForPath(or, "a.b",
                                                                                  tree).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a.b", tree));
            NUnit.Framework.Assert.AreEqual(null, TreeWalk.ForPath(or, "/a.b/", tree));
            NUnit.Framework.Assert.AreEqual(aDotB.GetObjectId(), TreeWalk.ForPath(or, "a.b/",
                                                                                  tree).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(aZeroB.GetObjectId(), TreeWalk.ForPath(or, "a0b",
                                                                                   tree).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(aSlashB.GetObjectId(), TreeWalk.ForPath(or, "a/b"
                                                                                    , tree).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(aSlashB.GetObjectId(), TreeWalk.ForPath(or, "b",
                                                                                    a).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(aSlashC, TreeWalk.ForPath(or, "a/c", tree).GetObjectId
                                                (0));
            NUnit.Framework.Assert.AreEqual(aSlashC, TreeWalk.ForPath(or, "c", a).GetObjectId
                                                (0));
            NUnit.Framework.Assert.AreEqual(aSlashCSlashD.GetObjectId(), TreeWalk.ForPath(or,
                                                                                          "a/c/d", tree).GetObjectId(0));
            NUnit.Framework.Assert.AreEqual(aSlashCSlashD.GetObjectId(), TreeWalk.ForPath(or,
                                                                                          "c/d", a).GetObjectId(0));
            or.Release();
            oi.Release();
        }