public override void skipEntriesEqual()
        {
            AbstractTreeIterator ch = CurrentHead;

            for (int i = 0; i < Trees.Length; i++)
            {
                AbstractTreeIterator t = Trees[i];
                if (t.Matches != ch)
                {
                    continue;
                }

                if (t.MatchShift == 0)
                {
                    t.skip();
                }
                else
                {
                    t.back(t.MatchShift);
                    t.MatchShift = 0;
                }

                t.Matches = null;
            }
        }
Beispiel #2
0
        /// <summary>A conflict is detected - add the three different stages to the index</summary>
        /// <param name="path">the path of the conflicting entry</param>
        /// <param name="e">the previous index entry</param>
        /// <param name="h">the first tree you want to merge (the HEAD)</param>
        /// <param name="m">the second tree you want to merge</param>
        private void Conflict(string path, DirCacheEntry e, AbstractTreeIterator h, AbstractTreeIterator
                              m)
        {
            conflicts.AddItem(path);
            DirCacheEntry entry;

            if (e != null)
            {
                entry = new DirCacheEntry(e.PathString, DirCacheEntry.STAGE_1);
                entry.CopyMetaData(e);
                builder.Add(entry);
            }
            if (h != null && !FileMode.TREE.Equals(h.EntryFileMode))
            {
                entry          = new DirCacheEntry(h.EntryPathString, DirCacheEntry.STAGE_2);
                entry.FileMode = h.EntryFileMode;
                entry.SetObjectId(h.EntryObjectId);
                builder.Add(entry);
            }
            if (m != null && !FileMode.TREE.Equals(m.EntryFileMode))
            {
                entry          = new DirCacheEntry(m.EntryPathString, DirCacheEntry.STAGE_3);
                entry.FileMode = m.EntryFileMode;
                entry.SetObjectId(m.EntryObjectId);
                builder.Add(entry);
            }
        }
        public override AbstractTreeIterator min()
        {
            while (true)
            {
                AbstractTreeIterator minRef = FastMin();
                if (_fastMinHasMatch)
                {
                    return(minRef);
                }

                if (IsTree(minRef))
                {
                    if (SkipEntry(minRef))
                    {
                        foreach (AbstractTreeIterator t in Trees)
                        {
                            if (t.Matches != minRef)
                            {
                                continue;
                            }
                            t.next(1);
                            t.Matches = null;
                        }

                        continue;
                    }

                    return(minRef);
                }

                return(CombineDF(minRef));
            }
        }
Beispiel #4
0
 /// <summary>
 /// Set the tree used by this walk for finding
 /// <code>.gitmodules</code>
 /// .
 /// <p>
 /// The root tree is not read until the first submodule is encountered by the
 /// walk.
 /// <p>
 /// This method need only be called if constructing a walk manually instead of
 /// with one of the static factory methods above.
 /// </summary>
 /// <param name="tree">tree containing .gitmodules</param>
 /// <returns>this generator</returns>
 public virtual NGit.Submodule.SubmoduleWalk SetRootTree(AbstractTreeIterator tree
                                                         )
 {
     rootTree      = tree;
     modulesConfig = null;
     return(this);
 }
Beispiel #5
0
        /// <summary>Would unstashing overwrite local changes?</summary>
        /// <param name="stashIndexIter"></param>
        /// <param name="stashWorkingTreeIter"></param>
        /// <param name="headIter"></param>
        /// <param name="indexIter"></param>
        /// <param name="workingTreeIter"></param>
        /// <returns>true if unstash conflict, false otherwise</returns>
        private bool IsConflict(AbstractTreeIterator stashIndexIter, AbstractTreeIterator
                                stashWorkingTreeIter, AbstractTreeIterator headIter, AbstractTreeIterator indexIter
                                , AbstractTreeIterator workingTreeIter)
        {
            // Is the current index dirty?
            bool indexDirty = indexIter != null && (headIter == null || !IsEqualEntry(indexIter
                                                                                      , headIter));
            // Is the current working tree dirty?
            bool workingTreeDirty = workingTreeIter != null && (headIter == null || !IsEqualEntry
                                                                    (workingTreeIter, headIter));

            // Would unstashing overwrite existing index changes?
            if (indexDirty && stashIndexIter != null && indexIter != null && !IsEqualEntry(stashIndexIter
                                                                                           , indexIter))
            {
                return(true);
            }
            // Would unstashing overwrite existing working tree changes?
            if (workingTreeDirty && stashWorkingTreeIter != null && workingTreeIter != null &&
                !IsEqualEntry(stashWorkingTreeIter, workingTreeIter))
            {
                return(true);
            }
            return(false);
        }
Beispiel #6
0
 /// <summary>
 /// Create a generator and advance it to the submodule entry at the given
 /// path
 /// </summary>
 /// <param name="repository"></param>
 /// <param name="iterator">
 /// the root of a tree containing both a submodule at the given path
 /// and .gitmodules at the root.
 /// </param>
 /// <param name="path"></param>
 /// <returns>generator at given path, null if no submodule at given path</returns>
 /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
 public static NGit.Submodule.SubmoduleWalk ForPath(Repository repository, AbstractTreeIterator
                                                    iterator, string path)
 {
     NGit.Submodule.SubmoduleWalk generator = new NGit.Submodule.SubmoduleWalk(repository
                                                                               );
     try
     {
         generator.SetTree(iterator);
         PathFilter filter = PathFilter.Create(path);
         generator.SetFilter(filter);
         generator.SetRootTree(iterator);
         while (generator.Next())
         {
             if (filter.IsDone(generator.walk))
             {
                 return(generator);
             }
         }
     }
     catch (IOException e)
     {
         generator.Release();
         throw;
     }
     generator.Release();
     return(null);
 }
Beispiel #7
0
 private ContentSource Source(AbstractTreeIterator iterator)
 {
     if (iterator is WorkingTreeIterator)
     {
         return(ContentSource.Create((WorkingTreeIterator)iterator));
     }
     return(ContentSource.Create(reader));
 }
Beispiel #8
0
        /// <summary>
        /// Set the tree used by this walk for finding
        /// <code>.gitmodules</code>
        /// .
        /// <p>
        /// The root tree is not read until the first submodule is encountered by the
        /// walk.
        /// <p>
        /// This method need only be called if constructing a walk manually instead of
        /// with one of the static factory methods above.
        /// </summary>
        /// <param name="id">ID of a tree containing .gitmodules</param>
        /// <returns>this generator</returns>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        public virtual NGit.Submodule.SubmoduleWalk SetRootTree(AnyObjectId id)
        {
            CanonicalTreeParser p = new CanonicalTreeParser();

            p.Reset(walk.ObjectReader, id);
            rootTree      = p;
            modulesConfig = null;
            return(this);
        }
        public virtual void testCreateSubtreeIterator()
        {
            EmptyTreeIterator    etp = new EmptyTreeIterator();
            AbstractTreeIterator sub = etp.createSubtreeIterator(db);

            Assert.IsNotNull(sub);
            Assert.IsTrue(sub.first());
            Assert.IsTrue(sub.eof());
            Assert.IsTrue(sub is EmptyTreeIterator);
        }
Beispiel #10
0
        private bool IsEqualEntry(AbstractTreeIterator iter1, AbstractTreeIterator iter2)
        {
            if (!iter1.EntryFileMode.Equals(iter2.EntryFileMode))
            {
                return(false);
            }
            ObjectId id1 = iter1.EntryObjectId;
            ObjectId id2 = iter2.EntryObjectId;

            return(id1 != null?id1.Equals(id2) : id2 == null);
        }
Beispiel #11
0
        /// <summary>Determine the differences between two trees.</summary>
        /// <remarks>
        /// Determine the differences between two trees.
        /// No output is created, instead only the file paths that are different are
        /// returned. Callers may choose to format these paths themselves, or convert
        /// them into
        /// <see cref="NGit.Patch.FileHeader">NGit.Patch.FileHeader</see>
        /// instances with a complete edit list by
        /// calling
        /// <see cref="ToFileHeader(DiffEntry)">ToFileHeader(DiffEntry)</see>
        /// .
        /// </remarks>
        /// <param name="a">the old (or previous) side.</param>
        /// <param name="b">the new (or updated) side.</param>
        /// <returns>the paths that are different.</returns>
        /// <exception cref="System.IO.IOException">trees cannot be read or file contents cannot be read.
        ///     </exception>
        public virtual IList <DiffEntry> Scan(AbstractTreeIterator a, AbstractTreeIterator
                                              b)
        {
            AssertHaveRepository();
            TreeWalk walk = new TreeWalk(reader);

            walk.AddTree(a);
            walk.AddTree(b);
            walk.Recursive = true;
            TreeFilter filter = GetDiffTreeFilterFor(a, b);

            if (pathFilter is FollowFilter)
            {
                walk.Filter = AndTreeFilter.Create(PathFilter.Create(((FollowFilter)pathFilter).GetPath
                                                                         ()), filter);
            }
            else
            {
                walk.Filter = AndTreeFilter.Create(pathFilter, filter);
            }
            source = new ContentSource.Pair(Source(a), Source(b));
            IList <DiffEntry> files = DiffEntry.Scan(walk);

            if (pathFilter is FollowFilter && IsAdd(files))
            {
                // The file we are following was added here, find where it
                // came from so we can properly show the rename or copy,
                // then continue digging backwards.
                //
                a.Reset();
                b.Reset();
                walk.Reset();
                walk.AddTree(a);
                walk.AddTree(b);
                walk.Filter = filter;
                if (renameDetector == null)
                {
                    SetDetectRenames(true);
                }
                files = UpdateFollowFilter(DetectRenames(DiffEntry.Scan(walk)));
            }
            else
            {
                if (renameDetector != null)
                {
                    files = DetectRenames(files);
                }
            }
            return(files);
        }
        public void testSimpleIterate()
        {
            var top = new FileTreeIterator(trash);

            Assert.IsTrue(top.first());
            Assert.IsFalse(top.eof());
            Assert.IsTrue(FileMode.RegularFile == top.EntryFileMode);
            Assert.AreEqual(Paths[0], NameOf(top));
            Assert.AreEqual(Paths[0].Length, top.getEntryLength());
            Assert.AreEqual(_mtime[0], top.getEntryLastModified());

            top.next(1);
            Assert.IsFalse(top.first());
            Assert.IsFalse(top.eof());
            Assert.IsTrue(FileMode.RegularFile == top.EntryFileMode);
            Assert.AreEqual(Paths[1], NameOf(top));
            Assert.AreEqual(Paths[1].Length, top.getEntryLength());
            Assert.AreEqual(_mtime[1], top.getEntryLastModified());

            top.next(1);
            Assert.IsFalse(top.first());
            Assert.IsFalse(top.eof());
            Assert.IsTrue(FileMode.Tree == top.EntryFileMode);

            AbstractTreeIterator sub = top.createSubtreeIterator(db);

            Assert.IsTrue(sub is FileTreeIterator);
            var subfti = (FileTreeIterator)sub;

            Assert.IsTrue(sub.first());
            Assert.IsFalse(sub.eof());
            Assert.AreEqual(Paths[2], NameOf(sub));
            Assert.AreEqual(Paths[2].Length, subfti.getEntryLength());
            Assert.AreEqual(_mtime[2], subfti.getEntryLastModified());

            sub.next(1);
            Assert.IsTrue(sub.eof());

            top.next(1);
            Assert.IsFalse(top.first());
            Assert.IsFalse(top.eof());
            Assert.IsTrue(FileMode.RegularFile == top.EntryFileMode);
            Assert.AreEqual(Paths[3], NameOf(top));
            Assert.AreEqual(Paths[3].Length, top.getEntryLength());
            Assert.AreEqual(_mtime[3], top.getEntryLastModified());

            top.next(1);
            Assert.IsTrue(top.eof());
        }
Beispiel #13
0
        /// <exception cref="System.IO.IOException"></exception>
        private void ApplyChanges(TreeWalk treeWalk, DirCache cache, DirCacheEditor editor
                                  )
        {
            FilePath workingTree = repo.WorkTree;

            while (treeWalk.Next())
            {
                string   path = treeWalk.PathString;
                FilePath file = new FilePath(workingTree, path);
                // State of the stashed HEAD, index, and working directory
                AbstractTreeIterator stashHeadIter    = treeWalk.GetTree <AbstractTreeIterator>(0);
                AbstractTreeIterator stashIndexIter   = treeWalk.GetTree <AbstractTreeIterator>(1);
                AbstractTreeIterator stashWorkingIter = treeWalk.GetTree <AbstractTreeIterator>(2);
                if (stashWorkingIter != null && stashIndexIter != null)
                {
                    // Checkout index change
                    DirCacheEntry entry = cache.GetEntry(path);
                    if (entry == null)
                    {
                        entry = new DirCacheEntry(treeWalk.RawPath);
                    }
                    entry.FileMode = stashIndexIter.EntryFileMode;
                    entry.SetObjectId(stashIndexIter.EntryObjectId);
                    DirCacheCheckout.CheckoutEntry(repo, file, entry, treeWalk.ObjectReader);
                    DirCacheEntry updatedEntry = entry;
                    editor.Add(new _PathEdit_270(updatedEntry, path));
                    // Checkout working directory change
                    if (!stashWorkingIter.IdEqual(stashIndexIter))
                    {
                        entry = new DirCacheEntry(treeWalk.RawPath);
                        entry.SetObjectId(stashWorkingIter.EntryObjectId);
                        DirCacheCheckout.CheckoutEntry(repo, file, entry, treeWalk.ObjectReader);
                    }
                }
                else
                {
                    if (stashIndexIter == null || (stashHeadIter != null && !stashIndexIter.IdEqual(stashHeadIter
                                                                                                    )))
                    {
                        editor.Add(new DirCacheEditor.DeletePath(path));
                    }
                    FileUtils.Delete(file, FileUtils.RETRY | FileUtils.SKIP_MISSING);
                }
            }
        }
Beispiel #14
0
        /// <exception cref="System.IO.IOException"></exception>
        private void ResetIndex(RevCommit commit)
        {
            DirCache dc   = repo.LockDirCache();
            TreeWalk walk = null;

            try
            {
                DirCacheEditor editor = dc.Editor();
                walk = new TreeWalk(repo);
                walk.AddTree(commit.Tree);
                walk.AddTree(new DirCacheIterator(dc));
                walk.Recursive = true;
                while (walk.Next())
                {
                    AbstractTreeIterator cIter = walk.GetTree <AbstractTreeIterator>(0);
                    if (cIter == null)
                    {
                        editor.Add(new DirCacheEditor.DeletePath(walk.PathString));
                        continue;
                    }
                    DirCacheEntry entry = new DirCacheEntry(walk.RawPath);
                    entry.FileMode = cIter.EntryFileMode;
                    entry.SetObjectIdFromRaw(cIter.IdBuffer, cIter.IdOffset);
                    DirCacheIterator dcIter = walk.GetTree <DirCacheIterator>(1);
                    if (dcIter != null && dcIter.IdEqual(cIter))
                    {
                        DirCacheEntry indexEntry = dcIter.GetDirCacheEntry();
                        entry.LastModified = indexEntry.LastModified;
                        entry.SetLength(indexEntry.Length);
                    }
                    editor.Add(new _PathEdit_356(entry, entry));
                }
                editor.Commit();
            }
            finally
            {
                dc.Unlock();
                if (walk != null)
                {
                    walk.Release();
                }
            }
        }
        private bool SkipEntry(AbstractTreeIterator minRef)
        {
            // A tree D/F may have been handled earlier. We need to
            // not report this path if it has already been reported.
            //
            foreach (AbstractTreeIterator t in Trees)
            {
                if (t.Matches == minRef || t.first())
                {
                    continue;
                }

                int stepsBack = 0;
                while (true)
                {
                    stepsBack++;
                    t.back(1);

                    int cmp = t.pathCompare(minRef, 0);
                    if (cmp == 0)
                    {
                        // We have already seen this "$path" before. Skip it.
                        //
                        t.next(stepsBack);
                        return(true);
                    }

                    if (cmp >= 0 && !t.first())
                    {
                        continue;
                    }

                    // We cannot find "$path" in t; it will never appear.
                    //
                    t.next(stepsBack);
                    break;
                }
            }

            // We have never seen the current path before.
            //
            return(false);
        }
            /// <exception cref="System.IO.IOException"></exception>
            private void Add(int tree, int stage)
            {
                AbstractTreeIterator i = GetTree(tree);

                if (i != null)
                {
                    if (FileMode.TREE.Equals(tw.GetRawMode(tree)))
                    {
                        builder.AddTree(tw.RawPath, stage, reader, tw.GetObjectId(tree));
                    }
                    else
                    {
                        DirCacheEntry e;
                        e = new DirCacheEntry(tw.RawPath, stage);
                        e.SetObjectIdFromRaw(i.IdBuffer, i.IdOffset);
                        e.FileMode = tw.GetFileMode(tree);
                        builder.Add(e);
                    }
                }
            }
            private void Add(int tree, int stage)
            {
                AbstractTreeIterator i = GetTree(tree);

                if (i == null)
                {
                    return;
                }

                if (FileMode.Tree.Equals(_tw.getRawMode(tree)))
                {
                    _builder.addTree(_tw.getRawPath(), stage, Repository, _tw.getObjectId(tree));
                }
                else
                {
                    var e = new DirCacheEntry(_tw.getRawPath(), stage);
                    e.setObjectIdFromRaw(i.idBuffer(), i.idOffset());
                    e.setFileMode(_tw.getFileMode(tree));
                    _builder.add(e);
                }
            }
Beispiel #18
0
        /// <exception cref="System.IO.IOException"></exception>
        private void ScanForConflicts(TreeWalk treeWalk)
        {
            FilePath workingTree = repo.WorkTree;

            while (treeWalk.Next())
            {
                // State of the stashed index and working directory
                AbstractTreeIterator stashIndexIter   = treeWalk.GetTree <AbstractTreeIterator>(1);
                AbstractTreeIterator stashWorkingIter = treeWalk.GetTree <AbstractTreeIterator>(2);
                // State of the current HEAD, index, and working directory
                AbstractTreeIterator headIter    = treeWalk.GetTree <AbstractTreeIterator>(3);
                AbstractTreeIterator indexIter   = treeWalk.GetTree <AbstractTreeIterator>(4);
                AbstractTreeIterator workingIter = treeWalk.GetTree <AbstractTreeIterator>(5);
                if (IsConflict(stashIndexIter, stashWorkingIter, headIter, indexIter, workingIter
                               ))
                {
                    string   path = treeWalk.PathString;
                    FilePath file = new FilePath(workingTree, path);
                    throw new NGit.Errors.CheckoutConflictException(file.GetAbsolutePath());
                }
            }
        }
        public override void popEntriesEqual()
        {
            AbstractTreeIterator ch = CurrentHead;

            for (int i = 0; i < Trees.Length; i++)
            {
                AbstractTreeIterator t = Trees[i];
                if (t.Matches == ch)
                {
                    if (t.MatchShift == 0)
                    {
                        t.next(1);
                    }
                    else
                    {
                        t.back(t.MatchShift);
                        t.MatchShift = 0;
                    }
                    t.Matches = null;
                }
            }
        }
Beispiel #20
0
        private static TreeFilter GetDiffTreeFilterFor(AbstractTreeIterator a, AbstractTreeIterator
                                                       b)
        {
            if (a is DirCacheIterator && b is WorkingTreeIterator)
            {
                return(new IndexDiffFilter(0, 1));
            }
            if (a is WorkingTreeIterator && b is DirCacheIterator)
            {
                return(new IndexDiffFilter(1, 0));
            }
            TreeFilter filter = TreeFilter.ANY_DIFF;

            if (a is WorkingTreeIterator)
            {
                filter = AndTreeFilter.Create(new NotIgnoredFilter(0), filter);
            }
            if (b is WorkingTreeIterator)
            {
                filter = AndTreeFilter.Create(new NotIgnoredFilter(1), filter);
            }
            return(filter);
        }
 private static string NameOf(AbstractTreeIterator i)
 {
     return(RawParseUtils.decode(Constants.CHARSET, i.Path, 0, i.PathLen));
 }
Beispiel #22
0
 /// <summary>Format the differences between two trees.</summary>
 /// <remarks>
 /// Format the differences between two trees.
 /// The patch is expressed as instructions to modify
 /// <code>a</code>
 /// to make it
 /// <code>b</code>
 /// .
 /// </remarks>
 /// <param name="a">the old (or previous) side.</param>
 /// <param name="b">the new (or updated) side.</param>
 /// <exception cref="System.IO.IOException">
 /// trees cannot be read, file contents cannot be read, or the
 /// patch cannot be output.
 /// </exception>
 public virtual void Format(AbstractTreeIterator a, AbstractTreeIterator b)
 {
     Format(Scan(a, b));
 }
 public EmptyTreeIterator(AbstractTreeIterator p)
     : base(p)
 {
     pathLen = pathOffset;
 }
Beispiel #24
0
 /// <summary>
 /// Create an iterator for a subtree of an existing iterator.
 /// The caller is responsible for setting up the path of the child iterator.
 /// </summary>
 /// <param name="parentIterator">Parent tree iterator.</param>
 public EmptyTreeIterator(AbstractTreeIterator parentIterator)
     : base(parentIterator)
 {
     PathLen = PathOffset;
 }
Beispiel #25
0
 /// <summary>
 /// Create an iterator for a subtree of an existing iterator.
 /// The caller is responsible for setting up the path of the child iterator.
 /// </summary>
 /// <param name="parent">Parent tree iterator.</param>
 /// <param name="childPath">
 /// Path array to be used by the child iterator. This path must
 /// contain the path from the top of the walk to the first child
 /// and must end with a '/'.
 /// </param>
 /// <param name="childPathOffset">
 /// position within <paramref name="childPath"/> where the child can
 /// insert its data. The value at
 /// <code><paramref name="childPath"/>[<paramref name="childPathOffset"/>-1]</code>
 /// must be '/'.
 /// </param>
 public EmptyTreeIterator(AbstractTreeIterator parent, byte[] childPath, int childPathOffset)
     : base(parent, childPath, childPathOffset)
 {
     PathLen = childPathOffset - 1;
 }
        private AbstractTreeIterator CombineDF(AbstractTreeIterator minRef)
        {
            // Look for a possible D/F conflict forward in the tree(s)
            // as there may be a "$path/" which matches "$path". Make
            // such entries match this entry.
            //
            AbstractTreeIterator treeMatch = null;

            foreach (AbstractTreeIterator t in Trees)
            {
                if (t.Matches == minRef || t.eof())
                {
                    continue;
                }

                for (; ;)
                {
                    int cmp = t.pathCompare(minRef, TreeMode);
                    if (cmp < 0)
                    {
                        // The "$path/" may still appear later.
                        //
                        t.MatchShift++;
                        t.next(1);
                        if (t.eof())
                        {
                            t.back(t.MatchShift);
                            t.MatchShift = 0;
                            break;
                        }
                    }
                    else if (cmp == 0)
                    {
                        // We have a conflict match here.
                        //
                        t.Matches = minRef;
                        treeMatch = t;
                        break;
                    }
                    else
                    {
                        // A conflict match is not possible.
                        //
                        if (t.MatchShift != 0)
                        {
                            t.back(t.MatchShift);
                            t.MatchShift = 0;
                        }
                        break;
                    }
                }
            }

            if (treeMatch != null)
            {
                // If we do have a conflict use one of the directory
                // matching iterators instead of the file iterator.
                // This way isSubtree is true and isRecursive works.
                //
                foreach (AbstractTreeIterator t in Trees)
                {
                    if (t.Matches == minRef)
                    {
                        t.Matches = treeMatch;
                    }
                }

                return(treeMatch);
            }

            return(minRef);
        }
 private static bool IsTree(AbstractTreeIterator p)
 {
     return FileMode.Tree == p.EntryFileMode;
 }
Beispiel #28
0
 private static bool nameEqual(AbstractTreeIterator a,
     AbstractTreeIterator b)
 {
     return a.pathCompare(b, TREE_MODE) == 0;
 }
Beispiel #29
0
		/// <summary>
		/// Create an iterator for a subtree of an existing iterator.
		/// The caller is responsible for setting up the path of the child iterator.
		/// </summary>
		/// <param name="parent">Parent tree iterator.</param>
		/// <param name="childPath">
		/// Path array to be used by the child iterator. This path must
		/// contain the path from the top of the walk to the first child
		/// and must end with a '/'.
		/// </param>
		/// <param name="childPathOffset">
		/// position within <paramref name="childPath"/> where the child can
		/// insert its data. The value at
		/// <code><paramref name="childPath"/>[<paramref name="childPathOffset"/>-1]</code> 
		/// must be '/'.
		/// </param>
        public EmptyTreeIterator(AbstractTreeIterator parent, byte[] childPath, int childPathOffset)
            : base(parent, childPath, childPathOffset)
        {
            PathLen = childPathOffset - 1;
        }
        private GitFileStatus GetFileStatus(TreeWalk treeWalk)
        {
            AbstractTreeIterator treeIterator        = treeWalk.GetTree <AbstractTreeIterator>(TREE);
            DirCacheIterator     dirCacheIterator    = treeWalk.GetTree <DirCacheIterator>(INDEX);
            WorkingTreeIterator  workingTreeIterator = treeWalk.GetTree <WorkingTreeIterator>(WORKDIR);

            if (dirCacheIterator != null)
            {
                DirCacheEntry dirCacheEntry = dirCacheIterator.GetDirCacheEntry();
                if (dirCacheEntry != null && dirCacheEntry.Stage > 0)
                {
                    return(GitFileStatus.Conflict);
                }

                if (workingTreeIterator == null)
                {
                    // in index, not in workdir => missing
                    return(GitFileStatus.Deleted);
                }
                else
                {
                    if (workingTreeIterator.IsModified(dirCacheIterator.GetDirCacheEntry(), true))
                    {
                        // in index, in workdir, content differs => modified
                        return(GitFileStatus.Modified);
                    }
                }
            }
            if (treeIterator != null)
            {
                if (dirCacheIterator != null)
                {
                    if (!treeIterator.IdEqual(dirCacheIterator) || treeIterator.EntryRawMode != dirCacheIterator.EntryRawMode)
                    {
                        // in repo, in index, content diff => changed
                        return(GitFileStatus.Staged);
                    }
                }
                else
                {
                    return(GitFileStatus.Removed);
                }
            }
            else
            {
                if (dirCacheIterator != null)
                {
                    // not in repo, in index => added
                    return(GitFileStatus.Added);
                }
                else
                {
                    // not in repo, not in index => untracked
                    if (workingTreeIterator != null)
                    {
                        return(!workingTreeIterator.IsEntryIgnored() ? GitFileStatus.New : GitFileStatus.Ignored);
                    }
                }
            }

            return(GitFileStatus.NotControlled);
        }
        private AbstractTreeIterator CombineDF(AbstractTreeIterator minRef)
        {
            // Look for a possible D/F conflict forward in the tree(s)
            // as there may be a "$path/" which matches "$path". Make
            // such entries match this entry.
            //
            AbstractTreeIterator treeMatch = null;
            foreach (AbstractTreeIterator t in Trees)
            {
                if (t.Matches == minRef || t.eof()) continue;

                for (; ; )
                {
                    int cmp = t.pathCompare(minRef, TreeMode);
                    if (cmp < 0)
                    {
                        // The "$path/" may still appear later.
                        //
                        t.MatchShift++;
                        t.next(1);
                        if (t.eof())
                        {
                            t.back(t.MatchShift);
                            t.MatchShift = 0;
                            break;
                        }
                    }
                    else if (cmp == 0)
                    {
                        // We have a conflict match here.
                        //
                        t.Matches = minRef;
                        treeMatch = t;
                        break;
                    }
                    else
                    {
                        // A conflict match is not possible.
                        //
                        if (t.MatchShift != 0)
                        {
                            t.back(t.MatchShift);
                            t.MatchShift = 0;
                        }
                        break;
                    }
                }
            }

            if (treeMatch != null)
            {
                // If we do have a conflict use one of the directory
                // matching iterators instead of the file iterator.
                // This way isSubtree is true and isRecursive works.
                //
                foreach (AbstractTreeIterator t in Trees)
                {
                    if (t.Matches == minRef)
                    {
                        t.Matches = treeMatch;
                    }
                }

                return treeMatch;
            }

            return minRef;
        }
 private static bool NameEqual(AbstractTreeIterator a,
     AbstractTreeIterator b)
 {
     return a.pathCompare(b, TreeMode) == 0;
 }
Beispiel #33
0
        /// <summary>
        /// Run the diff operation. Until this is called, all lists will be empty
        /// </summary>
        /// <returns>true if anything is different between index, tree, and workdir</returns>
        private void UpdateDirectory(IEnumerable <string> paths, bool recursive)
        {
            RevWalk  rw     = new RevWalk(Repository);
            ObjectId id     = Repository.Resolve(Constants.HEAD);
            var      commit = id != null?rw.ParseCommit(id) : null;

            TreeWalk treeWalk = new TreeWalk(Repository);

            treeWalk.Reset();
            treeWalk.Recursive = false;

            if (commit != null)
            {
                treeWalk.AddTree(commit.Tree);
            }
            else
            {
                treeWalk.AddTree(new EmptyTreeIterator());
            }

            DirCache dc = Repository.ReadDirCache();

            treeWalk.AddTree(new DirCacheIterator(dc));

            FileTreeIterator workTree = new FileTreeIterator(Repository.WorkTree, Repository.FileSystem, WorkingTreeOptions.KEY.Parse(Repository.GetConfig()));

            treeWalk.AddTree(workTree);

            List <TreeFilter> filters = new List <TreeFilter> ();

            filters.Add(new SkipWorkTreeFilter(1));

            var pathFilters = paths.Where(p => p != ".").Select(p => PathFilter.Create(p)).ToArray();

            if (pathFilters.Length > 1)
            {
                filters.Add(OrTreeFilter.Create(pathFilters));                   // Use an OR to join all path filters
            }
            else if (pathFilters.Length == 1)
            {
                filters.Add(pathFilters[0]);
            }

            if (filters.Count > 1)
            {
                treeWalk.Filter = AndTreeFilter.Create(filters);
            }
            else
            {
                treeWalk.Filter = filters[0];
            }

            while (treeWalk.Next())
            {
                AbstractTreeIterator treeIterator        = treeWalk.GetTree <AbstractTreeIterator>(0);
                DirCacheIterator     dirCacheIterator    = treeWalk.GetTree <DirCacheIterator>(1);
                WorkingTreeIterator  workingTreeIterator = treeWalk.GetTree <WorkingTreeIterator>(2);
                NGit.FileMode        fileModeTree        = treeWalk.GetFileMode(0);

                if (treeWalk.IsSubtree)
                {
                    treeWalk.EnterSubtree();
                    continue;
                }

                int stage = dirCacheIterator != null?dirCacheIterator.GetDirCacheEntry().Stage : 0;

                if (stage > 1)
                {
                    continue;
                }
                else if (stage == 1)
                {
                    MergeConflict.Add(dirCacheIterator.EntryPathString);
                    changesExist = true;
                    continue;
                }

                if (treeIterator != null)
                {
                    if (dirCacheIterator != null)
                    {
                        if (!treeIterator.EntryObjectId.Equals(dirCacheIterator.EntryObjectId))
                        {
                            // in repo, in index, content diff => changed
                            Modified.Add(dirCacheIterator.EntryPathString);
                            changesExist = true;
                        }
                    }
                    else
                    {
                        // in repo, not in index => removed
                        if (!fileModeTree.Equals(NGit.FileMode.TYPE_TREE))
                        {
                            Removed.Add(treeIterator.EntryPathString);
                            changesExist = true;
                        }
                    }
                }
                else
                {
                    if (dirCacheIterator != null)
                    {
                        // not in repo, in index => added
                        Added.Add(dirCacheIterator.EntryPathString);
                        changesExist = true;
                    }
                    else
                    {
                        // not in repo, not in index => untracked
                        if (workingTreeIterator != null && !workingTreeIterator.IsEntryIgnored())
                        {
                            Untracked.Add(workingTreeIterator.EntryPathString);
                            changesExist = true;
                        }
                    }
                }
                if (dirCacheIterator != null)
                {
                    if (workingTreeIterator == null)
                    {
                        // in index, not in workdir => missing
                        Missing.Add(dirCacheIterator.EntryPathString);
                        changesExist = true;
                    }
                    else
                    {
                        // Workaround to file time resolution issues
                        long itime = dirCacheIterator.GetDirCacheEntry().LastModified;
                        long ftime = workingTreeIterator.GetEntryLastModified();
                        if (itime / 1000 != ftime / 1000)
                        {
                            if (!dirCacheIterator.IdEqual(workingTreeIterator))
                            {
                                // in index, in workdir, content differs => modified
                                Modified.Add(dirCacheIterator.EntryPathString);
                                changesExist = true;
                            }
                        }
                    }
                }
            }
        }
        private bool SkipEntry(AbstractTreeIterator minRef)
        {
            // A tree D/F may have been handled earlier. We need to
            // not report this path if it has already been reported.
            //
            foreach (AbstractTreeIterator t in Trees)
            {
                if (t.Matches == minRef || t.first()) continue;

                int stepsBack = 0;
                while (true)
                {
                    stepsBack++;
                    t.back(1);

                    int cmp = t.pathCompare(minRef, 0);
                    if (cmp == 0)
                    {
                        // We have already seen this "$path" before. Skip it.
                        //
                        t.next(stepsBack);
                        return true;
                    }

                    if (cmp >= 0 && !t.first()) continue;

                    // We cannot find "$path" in t; it will never appear.
                    //
                    t.next(stepsBack);
                    break;
                }
            }

            // We have never seen the current path before.
            //
            return false;
        }
        private AbstractTreeIterator FastMin()
        {
            _fastMinHasMatch = true;

            int i = 0;
            AbstractTreeIterator minRef = Trees[i];

            while (minRef.eof() && ++i < Trees.Length)
            {
                minRef = Trees[i];
            }

            if (minRef.eof())
            {
                return(minRef);
            }

            minRef.Matches = minRef;
            while (++i < Trees.Length)
            {
                AbstractTreeIterator t = Trees[i];
                if (t.eof())
                {
                    continue;
                }

                int cmp = t.pathCompare(minRef);
                if (cmp < 0)
                {
                    if (_fastMinHasMatch && IsTree(minRef) && !IsTree(t) &&
                        NameEqual(minRef, t))
                    {
                        // We used to be at a tree, but now we are at a file
                        // with the same name. Allow the file to match the
                        // tree anyway.
                        //
                        t.Matches = minRef;
                    }
                    else
                    {
                        _fastMinHasMatch = false;
                        t.Matches        = t;
                        minRef           = t;
                    }
                }
                else if (cmp == 0)
                {
                    // Exact name/mode match is best.
                    //
                    t.Matches = minRef;
                }
                else if (_fastMinHasMatch && IsTree(t) && !IsTree(minRef) &&
                         NameEqual(t, minRef))
                {
                    // The minimum is a file (non-tree) but the next entry
                    // of this iterator is a tree whose name matches our file.
                    // This is a classic D/F conflict and commonly occurs like
                    // this, with no gaps in between the file and directory.
                    //
                    // Use the tree as the minimum instead (see CombineDF).
                    //

                    for (int k = 0; k < i; k++)
                    {
                        AbstractTreeIterator p = Trees[k];
                        if (p.Matches == minRef)
                        {
                            p.Matches = t;
                        }
                    }

                    t.Matches = t;
                    minRef    = t;
                }
                else
                {
                    _fastMinHasMatch = false;
                }
            }

            return(minRef);
        }
Beispiel #36
0
		/// <summary>
		/// Create an iterator for a subtree of an existing iterator.
		/// The caller is responsible for setting up the path of the child iterator.
		/// </summary>
		/// <param name="parentIterator">Parent tree iterator.</param>
        public EmptyTreeIterator(AbstractTreeIterator parentIterator)
            : base(parentIterator)
        {
            PathLen = PathOffset;
        }
 private static bool NameEqual(AbstractTreeIterator a,
                               AbstractTreeIterator b)
 {
     return(a.pathCompare(b, TreeMode) == 0);
 }
 private static bool IsTree(AbstractTreeIterator p)
 {
     return(FileMode.Tree == p.EntryFileMode);
 }
Beispiel #39
0
 private static bool isTree(AbstractTreeIterator p)
 {
     return FileMode.Tree.Equals(p.mode);
 }