Пример #1
0
		/// <summary>Construct a content source for a working directory.</summary>
		/// <remarks>
		/// Construct a content source for a working directory.
		/// If the iterator is a
		/// <see cref="NGit.Treewalk.FileTreeIterator">NGit.Treewalk.FileTreeIterator</see>
		/// an optimized version is
		/// used that doesn't require seeking through a TreeWalk.
		/// </remarks>
		/// <param name="iterator">the iterator to obtain source files through.</param>
		/// <returns>a content source wrapping the iterator.</returns>
		public static ContentSource Create(WorkingTreeIterator iterator)
		{
			if (iterator is FileTreeIterator)
			{
				FileTreeIterator i = (FileTreeIterator)iterator;
				return new ContentSource.FileSource(i.GetDirectory());
			}
			return new ContentSource.WorkingTreeSource(iterator);
		}
		public override NGit.Api.Status Call ()
		{
			if (iter == null)
				iter = new FileTreeIterator(repo);
			
			IndexDiff diff = new IndexDiff(repo, Constants.HEAD, iter);
			if (Files != null) {
				var filters = Files.Where (f => f != ".").ToArray ();
				if (filters.Length > 0)
					diff.SetFilter (PathFilterGroup.CreateFromStrings (filters));
			}
			
			diff.Diff ();
			return new NGit.Api.Status(diff);
		}
Пример #3
0
		public override NGit.Api.Status Call ()
		{
			if (iter == null)
				iter = new FileTreeIterator(repo);
			
			IndexDiff diff = new IndexDiff(repo, Constants.HEAD, iter);
			if (Files != null) {
				var filters = Files.Select (PathFilter.Create).ToArray ();
				if (filters.Length > 1)
					diff.SetFilter (OrTreeFilter.Create (filters));
				else
					diff.SetFilter (filters [0]);
			}
			
			diff.Diff ();
			return new NGit.Api.Status(diff);
		}
Пример #4
0
			/// <exception cref="System.IO.IOException"></exception>
			private void Seek(string path)
			{
				if (!path.Equals(current))
				{
					iterator.Reset();
					tw.Reset();
					tw.AddTree(iterator);
					tw.Filter = PathFilter.Create(path);
					current = path;
					if (!tw.Next())
					{
						throw new FileNotFoundException(path);
					}
					ptr = tw.GetTree<WorkingTreeIterator>(0);
					if (ptr == null)
					{
						throw new FileNotFoundException(path);
					}
				}
			}
Пример #5
0
        /// <summary>
        /// Executes the
        /// <code>Add</code>
        /// command. Each instance of this class should only
        /// be used for one invocation of the command. Don't call this method twice
        /// on an instance.
        /// </summary>
        /// <returns>the DirCache after Add</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException"></exception>
        /// <exception cref="NGit.Api.Errors.NoFilepatternException"></exception>
        public override DirCache Call()
        {
            if (filepatterns.IsEmpty())
            {
                throw new NoFilepatternException(JGitText.Get().atLeastOnePatternIsRequired);
            }
            CheckCallable();
            DirCache dc     = null;
            bool     addAll = false;

            if (filepatterns.Contains("."))
            {
                addAll = true;
            }
            ObjectInserter inserter = repo.NewObjectInserter();

            try
            {
                dc = repo.LockDirCache();
                DirCacheIterator c;
                DirCacheBuilder  builder = dc.Builder();
                TreeWalk         tw      = new TreeWalk(repo);
                tw.AddTree(new DirCacheBuildIterator(builder));
                if (workingTreeIterator == null)
                {
                    workingTreeIterator = new FileTreeIterator(repo);
                }
                tw.AddTree(workingTreeIterator);
                tw.Recursive = true;
                if (!addAll)
                {
                    tw.Filter = PathFilterGroup.CreateFromStrings(filepatterns);
                }
                string lastAddedFile = null;
                while (tw.Next())
                {
                    string path           = tw.PathString;
                    WorkingTreeIterator f = tw.GetTree <WorkingTreeIterator>(1);
                    if (tw.GetTree <DirCacheIterator>(0) == null && f != null && f.IsEntryIgnored())
                    {
                    }
                    else
                    {
                        // file is not in index but is ignored, do nothing
                        // In case of an existing merge conflict the
                        // DirCacheBuildIterator iterates over all stages of
                        // this path, we however want to add only one
                        // new DirCacheEntry per path.
                        if (!(path.Equals(lastAddedFile)))
                        {
                            if (!(update && tw.GetTree <DirCacheIterator>(0) == null))
                            {
                                c = tw.GetTree <DirCacheIterator>(0);
                                if (f != null)
                                {
                                    // the file exists
                                    long          sz    = f.GetEntryLength();
                                    DirCacheEntry entry = new DirCacheEntry(path);
                                    if (c == null || c.GetDirCacheEntry() == null || !c.GetDirCacheEntry().IsAssumeValid)
                                    {
                                        FileMode mode = f.GetIndexFileMode(c);
                                        entry.FileMode = mode;
                                        if (FileMode.GITLINK != mode)
                                        {
                                            entry.SetLength(sz);
                                            entry.LastModified = f.GetEntryLastModified();
                                            long        contentSize = f.GetEntryContentLength();
                                            InputStream @in         = f.OpenEntryStream();
                                            try
                                            {
                                                entry.SetObjectId(inserter.Insert(Constants.OBJ_BLOB, contentSize, @in));
                                            }
                                            finally
                                            {
                                                @in.Close();
                                            }
                                        }
                                        else
                                        {
                                            entry.SetObjectId(f.EntryObjectId);
                                        }
                                        builder.Add(entry);
                                        lastAddedFile = path;
                                    }
                                    else
                                    {
                                        builder.Add(c.GetDirCacheEntry());
                                    }
                                }
                                else
                                {
                                    if (c != null && (!update || FileMode.GITLINK == c.EntryFileMode))
                                    {
                                        builder.Add(c.GetDirCacheEntry());
                                    }
                                }
                            }
                        }
                    }
                }
                inserter.Flush();
                builder.Commit();
                SetCallable(false);
            }
            catch (IOException e)
            {
                throw new JGitInternalException(JGitText.Get().exceptionCaughtDuringExecutionOfAddCommand
                                                , e);
            }
            finally
            {
                inserter.Release();
                if (dc != null)
                {
                    dc.Unlock();
                }
            }
            return(dc);
        }
Пример #6
0
		/// <summary>Processes one path and tries to merge.</summary>
		/// <remarks>
		/// Processes one path and tries to merge. This method will do all do all
		/// trivial (not content) merges and will also detect if a merge will fail.
		/// The merge will fail when one of the following is true
		/// <ul>
		/// <li>the index entry does not match the entry in ours. When merging one
		/// branch into the current HEAD, ours will point to HEAD and theirs will
		/// point to the other branch. It is assumed that the index matches the HEAD
		/// because it will only not match HEAD if it was populated before the merge
		/// operation. But the merge commit should not accidentally contain
		/// modifications done before the merge. Check the &lt;a href=
		/// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
		/// &gt;git read-tree</a> documentation for further explanations.</li>
		/// <li>A conflict was detected and the working-tree file is dirty. When a
		/// conflict is detected the content-merge algorithm will try to write a
		/// merged version into the working-tree. If the file is dirty we would
		/// override unsaved data.</li>
		/// </remarks>
		/// <param name="base">the common base for ours and theirs</param>
		/// <param name="ours">
		/// the ours side of the merge. When merging a branch into the
		/// HEAD ours will point to HEAD
		/// </param>
		/// <param name="theirs">
		/// the theirs side of the merge. When merging a branch into the
		/// current HEAD theirs will point to the branch which is merged
		/// into HEAD.
		/// </param>
		/// <param name="index">the index entry</param>
		/// <param name="work">the file in the working tree</param>
		/// <returns>
		/// <code>false</code> if the merge will fail because the index entry
		/// didn't match ours or the working-dir file was dirty and a
		/// conflict occured
		/// </returns>
		/// <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>
		private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser
			 theirs, DirCacheBuildIterator index, WorkingTreeIterator work)
		{
			enterSubtree = true;
			int modeO = tw.GetRawMode(T_OURS);
			int modeI = tw.GetRawMode(T_INDEX);
			// Each index entry has to match ours, means: it has to be clean
			if (NonTree(modeI) && !(tw.IdEqual(T_INDEX, T_OURS) && modeO == modeI))
			{
				failingPaths.Put(tw.PathString, ResolveMerger.MergeFailureReason.DIRTY_INDEX);
				return false;
			}
			int modeT = tw.GetRawMode(T_THEIRS);
			if (NonTree(modeO) && modeO == modeT && tw.IdEqual(T_OURS, T_THEIRS))
			{
				// ours and theirs are equal: it doesn'nt matter
				// which one we choose. OURS is choosen here.
				Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
				// no checkout needed!
				return true;
			}
			int modeB = tw.GetRawMode(T_BASE);
			if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
			{
				// THEIRS was not changed compared to base. All changes must be in
				// OURS. Choose OURS.
				Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
				return true;
			}
			if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
			{
				// OURS was not changed compared to base. All changes must be in
				// THEIRS. Choose THEIRS.
				if (NonTree(modeT))
				{
					DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
					if (e != null)
					{
						toBeCheckedOut.Put(tw.PathString, e);
					}
					return true;
				}
				else
				{
					if ((modeT == 0) && (modeB != 0))
					{
						// we want THEIRS ... but THEIRS contains the deletion of the
						// file
						toBeCheckedOut.Put(tw.PathString, null);
						return true;
					}
				}
			}
			if (tw.IsSubtree)
			{
				// file/folder conflicts: here I want to detect only file/folder
				// conflict between ours and theirs. file/folder conflicts between
				// base/index/workingTree and something else are not relevant or
				// detected later
				if (NonTree(modeO) && !NonTree(modeT))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
					}
					Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				if (NonTree(modeT) && !NonTree(modeO))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
					}
					Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				// ours and theirs are both folders or both files (and treewalk
				// tells us we are in a subtree because of index or working-dir).
				// If they are both folders no content-merge is required - we can
				// return here.
				if (!NonTree(modeO))
				{
					return true;
				}
			}
			// ours and theirs are both files, just fall out of the if block
			// and do the content merge
			if (NonTree(modeO) && NonTree(modeT))
			{
				if (!inCore)
				{
					// We are going to update the worktree. Make sure the worktree
					// is not modified
					if (work != null && (!NonTree(work.EntryRawMode) || work.IsModified(index.GetDirCacheEntry
						(), true)))
					{
						failingPaths.Put(tw.PathString, ResolveMerger.MergeFailureReason.DIRTY_WORKTREE);
						return false;
					}
				}
				if (!ContentMerge(@base, ours, theirs))
				{
					unmergedPaths.AddItem(tw.PathString);
				}
				modifiedFiles.AddItem(tw.PathString);
			}
			return true;
		}
Пример #7
0
		/// <summary>Construct an Indexdiff</summary>
		/// <param name="repository"></param>
		/// <param name="objectId">tree id. If null, an EmptyTreeIterator is used.</param>
		/// <param name="workingTreeIterator">iterator for working directory</param>
		/// <exception cref="System.IO.IOException">System.IO.IOException</exception>
		public IndexDiff(Repository repository, ObjectId objectId, WorkingTreeIterator workingTreeIterator
			)
		{
			this.repository = repository;
			if (objectId != null)
			{
				tree = new RevWalk(repository).ParseTree(objectId);
			}
			else
			{
				tree = null;
			}
			this.initialWorkingTreeIterator = workingTreeIterator;
		}
Пример #8
0
 private bool IsWorktreeDirty(WorkingTreeIterator work)
 {
     if (inCore || work == null)
     {
         return false;
     }
     int modeF = tw.GetRawMode(T_FILE);
     int modeO = tw.GetRawMode(T_OURS);
     // Worktree entry has to match ours to be considered clean
     bool isDirty = work.IsModeDifferent(modeO);
     if (!isDirty && NonTree(modeF))
     {
         isDirty = !tw.IdEqual(T_FILE, T_OURS);
     }
     if (isDirty)
     {
         failingPaths.Put(tw.PathString, ResolveMerger.MergeFailureReason.DIRTY_WORKTREE);
     }
     return isDirty;
 }
Пример #9
0
        /// <summary>
        /// Processing an entry in the context of
        /// <see cref="PrescanOneTree()">PrescanOneTree()</see>
        /// when only
        /// one tree is given
        /// </summary>
        /// <param name="m">the tree to merge</param>
        /// <param name="i">the index</param>
        /// <param name="f">the working tree</param>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        internal virtual void ProcessEntry(CanonicalTreeParser m, DirCacheBuildIterator i
			, WorkingTreeIterator f)
        {
            if (m != null)
            {
                if (!IsValidPath(m))
                {
                    throw new InvalidPathException(m.EntryPathString);
                }
                // There is an entry in the merge commit. Means: we want to update
                // what's currently in the index and working-tree to that one
                if (i == null)
                {
                    // The index entry is missing
                    if (f != null && !FileMode.TREE.Equals(f.EntryFileMode) && !f.IsEntryIgnored())
                    {
                        // don't overwrite an untracked and not ignored file
                        conflicts.AddItem(walk.PathString);
                    }
                    else
                    {
                        Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
                    }
                }
                else
                {
                    if (f == null || !m.IdEqual(i))
                    {
                        // The working tree file is missing or the merge content differs
                        // from index content
                        Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
                    }
                    else
                    {
                        if (i.GetDirCacheEntry() != null)
                        {
                            // The index contains a file (and not a folder)
                            if (f.IsModified(i.GetDirCacheEntry(), true) || i.GetDirCacheEntry().Stage != 0)
                            {
                                // The working tree file is dirty or the index contains a
                                // conflict
                                Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
                            }
                            else
                            {
                                // update the timestamp of the index with the one from the
                                // file if not set, as we are sure to be in sync here.
                                DirCacheEntry entry = i.GetDirCacheEntry();
                                if (entry.LastModified == 0)
                                {
                                    entry.LastModified = f.GetEntryLastModified();
                                }
                                Keep(entry);
                            }
                        }
                        else
                        {
                            // The index contains a folder
                            Keep(i.GetDirCacheEntry());
                        }
                    }
                }
            }
            else
            {
                // There is no entry in the merge commit. Means: we want to delete
                // what's currently in the index and working tree
                if (f != null)
                {
                    // There is a file/folder for that path in the working tree
                    if (walk.IsDirectoryFileConflict())
                    {
                        conflicts.AddItem(walk.PathString);
                    }
                    else
                    {
                        // No file/folder conflict exists. All entries are files or
                        // all entries are folders
                        if (i != null)
                        {
                            // ... and the working tree contained a file or folder
                            // -> add it to the removed set and remove it from
                            // conflicts set
                            Remove(i.EntryPathString);
                            conflicts.Remove(i.EntryPathString);
                        }
                    }
                }
            }
        }
Пример #10
0
		/// <summary>Processes one path and tries to merge.</summary>
		/// <remarks>
		/// Processes one path and tries to merge. This method will do all do all
		/// trivial (not content) merges and will also detect if a merge will fail.
		/// The merge will fail when one of the following is true
		/// <ul>
		/// <li>the index entry does not match the entry in ours. When merging one
		/// branch into the current HEAD, ours will point to HEAD and theirs will
		/// point to the other branch. It is assumed that the index matches the HEAD
		/// because it will only not match HEAD if it was populated before the merge
		/// operation. But the merge commit should not accidentally contain
		/// modifications done before the merge. Check the &lt;a href=
		/// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
		/// &gt;git read-tree</a> documentation for further explanations.</li>
		/// <li>A conflict was detected and the working-tree file is dirty. When a
		/// conflict is detected the content-merge algorithm will try to write a
		/// merged version into the working-tree. If the file is dirty we would
		/// override unsaved data.</li>
		/// </remarks>
		/// <param name="base">the common base for ours and theirs</param>
		/// <param name="ours">
		/// the ours side of the merge. When merging a branch into the
		/// HEAD ours will point to HEAD
		/// </param>
		/// <param name="theirs">
		/// the theirs side of the merge. When merging a branch into the
		/// current HEAD theirs will point to the branch which is merged
		/// into HEAD.
		/// </param>
		/// <param name="index">the index entry</param>
		/// <param name="work">the file in the working tree</param>
		/// <returns>
		/// <code>false</code> if the merge will fail because the index entry
		/// didn't match ours or the working-dir file was dirty and a
		/// conflict occurred
		/// </returns>
		/// <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>
		private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser
			 theirs, DirCacheBuildIterator index, WorkingTreeIterator work)
		{
			enterSubtree = true;
			int modeO = tw.GetRawMode(T_OURS);
			int modeT = tw.GetRawMode(T_THEIRS);
			int modeB = tw.GetRawMode(T_BASE);
			if (modeO == 0 && modeT == 0 && modeB == 0)
			{
				// File is either untracked or new, staged but uncommitted
				return true;
			}
			if (IsIndexDirty())
			{
				return false;
			}
			if (NonTree(modeO) && modeO == modeT && tw.IdEqual(T_OURS, T_THEIRS))
			{
				// OURS and THEIRS are equal: it doesn't matter which one we choose.
				// OURS is chosen.
				Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
				// no checkout needed!
				return true;
			}
			if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
			{
				// THEIRS was not changed compared to BASE. All changes must be in
				// OURS. OURS is chosen.
				Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
				// no checkout needed!
				return true;
			}
			if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
			{
				// OURS was not changed compared to BASE. All changes must be in
				// THEIRS. THEIRS is chosen.
				// Check worktree before checking out THEIRS
				if (IsWorktreeDirty())
				{
					return false;
				}
				if (NonTree(modeT))
				{
					DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
					if (e != null)
					{
						toBeCheckedOut.Put(tw.PathString, e);
					}
					return true;
				}
				else
				{
					if (modeT == 0 && modeB != 0)
					{
						// we want THEIRS ... but THEIRS contains the deletion of the
						// file
						toBeCheckedOut.Put(tw.PathString, null);
						return true;
					}
				}
			}
			if (tw.IsSubtree)
			{
				// file/folder conflicts: here I want to detect only file/folder
				// conflict between ours and theirs. file/folder conflicts between
				// base/index/workingTree and something else are not relevant or
				// detected later
				if (NonTree(modeO) && !NonTree(modeT))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
					}
					Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				if (NonTree(modeT) && !NonTree(modeO))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
					}
					Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				// ours and theirs are both folders or both files (and treewalk
				// tells us we are in a subtree because of index or working-dir).
				// If they are both folders no content-merge is required - we can
				// return here.
				if (!NonTree(modeO))
				{
					return true;
				}
			}
			// ours and theirs are both files, just fall out of the if block
			// and do the content merge
			if (NonTree(modeO) && NonTree(modeT))
			{
				// Check worktree before modifying files
				if (IsWorktreeDirty())
				{
					return false;
				}
				if (!ContentMerge(@base, ours, theirs))
				{
					unmergedPaths.AddItem(tw.PathString);
				}
				modifiedFiles.AddItem(tw.PathString);
			}
			return true;
		}
        /// <exception cref="NGit.Errors.MissingObjectException"></exception>
        /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        public override bool Include(TreeWalk tw)
        {
            WorkingTreeIterator i = tw.GetTree <WorkingTreeIterator>(index);

            return(i == null || !i.IsEntryIgnored());
        }
Пример #12
0
 /// <summary>Sets the WorkingTreeIterator to be used by this merger.</summary>
 /// <remarks>
 /// Sets the WorkingTreeIterator to be used by this merger. If no
 /// WorkingTreeIterator is set this merger will ignore the working tree and
 /// fail if a content merge is necessary.
 /// <p>
 /// TODO: enhance WorkingTreeIterator to support write operations. Then this
 /// merger will be able to merge with a different working tree abstraction.
 /// </remarks>
 /// <param name="workingTreeIterator">the workingTreeIt to set</param>
 public virtual void SetWorkingTreeIterator(WorkingTreeIterator workingTreeIterator
                                            )
 {
     this.workingTreeIterator = workingTreeIterator;
 }
Пример #13
0
        /// <summary>Processes one path and tries to merge.</summary>
        /// <remarks>
        /// Processes one path and tries to merge. This method will do all do all
        /// trivial (not content) merges and will also detect if a merge will fail.
        /// The merge will fail when one of the following is true
        /// <ul>
        /// <li>the index entry does not match the entry in ours. When merging one
        /// branch into the current HEAD, ours will point to HEAD and theirs will
        /// point to the other branch. It is assumed that the index matches the HEAD
        /// because it will only not match HEAD if it was populated before the merge
        /// operation. But the merge commit should not accidentally contain
        /// modifications done before the merge. Check the &lt;a href=
        /// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
        /// &gt;git read-tree</a> documentation for further explanations.</li>
        /// <li>A conflict was detected and the working-tree file is dirty. When a
        /// conflict is detected the content-merge algorithm will try to write a
        /// merged version into the working-tree. If the file is dirty we would
        /// override unsaved data.</li>
        /// </remarks>
        /// <param name="base">the common base for ours and theirs</param>
        /// <param name="ours">
        /// the ours side of the merge. When merging a branch into the
        /// HEAD ours will point to HEAD
        /// </param>
        /// <param name="theirs">
        /// the theirs side of the merge. When merging a branch into the
        /// current HEAD theirs will point to the branch which is merged
        /// into HEAD.
        /// </param>
        /// <param name="index">the index entry</param>
        /// <param name="work">the file in the working tree</param>
        /// <returns>
        /// <code>false</code> if the merge will fail because the index entry
        /// didn't match ours or the working-dir file was dirty and a
        /// conflict occurred
        /// </returns>
        /// <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>
        private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser
                                  theirs, DirCacheBuildIterator index, WorkingTreeIterator work)
        {
            enterSubtree = true;
            int modeO = tw.GetRawMode(T_OURS);
            int modeT = tw.GetRawMode(T_THEIRS);
            int modeB = tw.GetRawMode(T_BASE);

            if (modeO == 0 && modeT == 0 && modeB == 0)
            {
                // File is either untracked or new, staged but uncommitted
                return(true);
            }
            if (IsIndexDirty())
            {
                return(false);
            }
            if (NonTree(modeO) && NonTree(modeT) && tw.IdEqual(T_OURS, T_THEIRS))
            {
                // OURS and THEIRS have equal content. Check the file mode
                if (modeO == modeT)
                {
                    // content and mode of OURS and THEIRS are equal: it doesn't
                    // matter which one we choose. OURS is chosen.
                    Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                    // no checkout needed!
                    return(true);
                }
                else
                {
                    // same content but different mode on OURS and THEIRS.
                    // Try to merge the mode and report an error if this is
                    // not possible.
                    int newMode = MergeFileModes(modeB, modeO, modeT);
                    if (newMode != FileMode.MISSING.GetBits())
                    {
                        if (newMode == modeO)
                        {
                            // ours version is preferred
                            Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                        }
                        else
                        {
                            // the preferred version THEIRS has a different mode
                            // than ours. Check it out!
                            if (IsWorktreeDirty(work))
                            {
                                return(false);
                            }
                            DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
                            toBeCheckedOut.Put(tw.PathString, e);
                        }
                        return(true);
                    }
                    else
                    {
                        // FileModes are not mergeable. We found a conflict on modes
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                        Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                        Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                        unmergedPaths.AddItem(tw.PathString);
                        mergeResults.Put(tw.PathString, new MergeResult <RawText>(Sharpen.Collections.EmptyList
                                                                                  <RawText>()).Upcast());
                    }
                    return(true);
                }
            }
            if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
            {
                // THEIRS was not changed compared to BASE. All changes must be in
                // OURS. OURS is chosen.
                Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                // no checkout needed!
                return(true);
            }
            if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
            {
                // OURS was not changed compared to BASE. All changes must be in
                // THEIRS. THEIRS is chosen.
                // Check worktree before checking out THEIRS
                if (IsWorktreeDirty(work))
                {
                    return(false);
                }
                if (NonTree(modeT))
                {
                    DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
                    if (e != null)
                    {
                        toBeCheckedOut.Put(tw.PathString, e);
                    }
                    return(true);
                }
                else
                {
                    if (modeT == 0 && modeB != 0)
                    {
                        // we want THEIRS ... but THEIRS contains the deletion of the
                        // file
                        toBeDeleted.AddItem(tw.PathString);
                        return(true);
                    }
                }
            }
            if (tw.IsSubtree)
            {
                // file/folder conflicts: here I want to detect only file/folder
                // conflict between ours and theirs. file/folder conflicts between
                // base/index/workingTree and something else are not relevant or
                // detected later
                if (NonTree(modeO) && !NonTree(modeT))
                {
                    if (NonTree(modeB))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                    }
                    Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                    unmergedPaths.AddItem(tw.PathString);
                    enterSubtree = false;
                    return(true);
                }
                if (NonTree(modeT) && !NonTree(modeO))
                {
                    if (NonTree(modeB))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                    }
                    Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                    unmergedPaths.AddItem(tw.PathString);
                    enterSubtree = false;
                    return(true);
                }
                // ours and theirs are both folders or both files (and treewalk
                // tells us we are in a subtree because of index or working-dir).
                // If they are both folders no content-merge is required - we can
                // return here.
                if (!NonTree(modeO))
                {
                    return(true);
                }
            }
            // ours and theirs are both files, just fall out of the if block
            // and do the content merge
            if (NonTree(modeO) && NonTree(modeT))
            {
                // Check worktree before modifying files
                if (IsWorktreeDirty(work))
                {
                    return(false);
                }
                MergeResult <RawText> result = ContentMerge(@base, ours, theirs);
                FilePath of = WriteMergedFile(result);
                UpdateIndex(@base, ours, theirs, result, of);
                if (result.ContainsConflicts())
                {
                    unmergedPaths.AddItem(tw.PathString);
                }
                modifiedFiles.AddItem(tw.PathString);
            }
            else
            {
                if (modeO != modeT)
                {
                    // OURS or THEIRS has been deleted
                    if (((modeO != 0 && !tw.IdEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw.IdEqual(T_BASE
                                                                                                   , T_THEIRS))))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                        Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                        DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                        // OURS was deleted checkout THEIRS
                        if (modeO == 0)
                        {
                            // Check worktree before checking out THEIRS
                            if (IsWorktreeDirty(work))
                            {
                                return(false);
                            }
                            if (NonTree(modeT))
                            {
                                if (e != null)
                                {
                                    toBeCheckedOut.Put(tw.PathString, e);
                                }
                            }
                        }
                        unmergedPaths.AddItem(tw.PathString);
                        // generate a MergeResult for the deleted file
                        mergeResults.Put(tw.PathString, ContentMerge(@base, ours, theirs).Upcast());
                    }
                }
            }
            return(true);
        }
Пример #14
0
		/// <summary>Processes one path and tries to merge.</summary>
		/// <remarks>
		/// Processes one path and tries to merge. This method will do all do all
		/// trivial (not content) merges and will also detect if a merge will fail.
		/// The merge will fail when one of the following is true
		/// <ul>
		/// <li>the index entry does not match the entry in ours. When merging one
		/// branch into the current HEAD, ours will point to HEAD and theirs will
		/// point to the other branch. It is assumed that the index matches the HEAD
		/// because it will only not match HEAD if it was populated before the merge
		/// operation. But the merge commit should not accidentally contain
		/// modifications done before the merge. Check the &lt;a href=
		/// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
		/// &gt;git read-tree</a> documentation for further explanations.</li>
		/// <li>A conflict was detected and the working-tree file is dirty. When a
		/// conflict is detected the content-merge algorithm will try to write a
		/// merged version into the working-tree. If the file is dirty we would
		/// override unsaved data.</li>
		/// </remarks>
		/// <param name="base">the common base for ours and theirs</param>
		/// <param name="ours">
		/// the ours side of the merge. When merging a branch into the
		/// HEAD ours will point to HEAD
		/// </param>
		/// <param name="theirs">
		/// the theirs side of the merge. When merging a branch into the
		/// current HEAD theirs will point to the branch which is merged
		/// into HEAD.
		/// </param>
		/// <param name="index">the index entry</param>
		/// <param name="work">the file in the working tree</param>
		/// <returns>
		/// <code>false</code> if the merge will fail because the index entry
		/// didn't match ours or the working-dir file was dirty and a
		/// conflict occurred
		/// </returns>
		/// <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>
		private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser
			 theirs, DirCacheBuildIterator index, WorkingTreeIterator work)
		{
			enterSubtree = true;
			int modeO = tw.GetRawMode(T_OURS);
			int modeT = tw.GetRawMode(T_THEIRS);
			int modeB = tw.GetRawMode(T_BASE);
			if (modeO == 0 && modeT == 0 && modeB == 0)
			{
				// File is either untracked or new, staged but uncommitted
				return true;
			}
			if (IsIndexDirty())
			{
				return false;
			}
			DirCacheEntry ourDce = null;
			if (index == null || index.GetDirCacheEntry() == null)
			{
				// create a fake DCE, but only if ours is valid. ours is kept only
				// in case it is valid, so a null ourDce is ok in all other cases.
				if (NonTree(modeO))
				{
					ourDce = new DirCacheEntry(tw.RawPath);
					ourDce.SetObjectId(tw.GetObjectId(T_OURS));
					ourDce.FileMode = tw.GetFileMode(T_OURS);
				}
			}
			else
			{
				ourDce = index.GetDirCacheEntry();
			}
			if (NonTree(modeO) && NonTree(modeT) && tw.IdEqual(T_OURS, T_THEIRS))
			{
				// OURS and THEIRS have equal content. Check the file mode
				if (modeO == modeT)
				{
					// content and mode of OURS and THEIRS are equal: it doesn't
					// matter which one we choose. OURS is chosen. Since the index
					// is clean (the index matches already OURS) we can keep the existing one
					Keep(ourDce);
					// no checkout needed!
					return true;
				}
				else
				{
					// same content but different mode on OURS and THEIRS.
					// Try to merge the mode and report an error if this is
					// not possible.
					int newMode = MergeFileModes(modeB, modeO, modeT);
					if (newMode != FileMode.MISSING.GetBits())
					{
						if (newMode == modeO)
						{
							// ours version is preferred
							Keep(ourDce);
						}
						else
						{
							// the preferred version THEIRS has a different mode
							// than ours. Check it out!
							if (IsWorktreeDirty(work))
							{
								return false;
							}
							// we know about length and lastMod only after we have written the new content.
							// This will happen later. Set these values to 0 for know.
							DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0, 0, 0);
							toBeCheckedOut.Put(tw.PathString, e);
						}
						return true;
					}
					else
					{
						// FileModes are not mergeable. We found a conflict on modes.
						// For conflicting entries we don't know lastModified and length.
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0);
						Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0);
						Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0);
						unmergedPaths.AddItem(tw.PathString);
						mergeResults.Put(tw.PathString, new MergeResult<RawText>(Sharpen.Collections.EmptyList
							<RawText>()).Upcast ());
					}
					return true;
				}
			}
			if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
			{
				// THEIRS was not changed compared to BASE. All changes must be in
				// OURS. OURS is chosen. We can keep the existing entry.
				Keep(ourDce);
				// no checkout needed!
				return true;
			}
			if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
			{
				// OURS was not changed compared to BASE. All changes must be in
				// THEIRS. THEIRS is chosen.
				// Check worktree before checking out THEIRS
				if (IsWorktreeDirty(work))
				{
					return false;
				}
				if (NonTree(modeT))
				{
					// we know about length and lastMod only after we have written
					// the new content.
					// This will happen later. Set these values to 0 for know.
					DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0, 0, 0);
					if (e != null)
					{
						toBeCheckedOut.Put(tw.PathString, e);
					}
					return true;
				}
				else
				{
					if (modeT == 0 && modeB != 0)
					{
						// we want THEIRS ... but THEIRS contains the deletion of the
						// file
						toBeDeleted.AddItem(tw.PathString);
						return true;
					}
				}
			}
			if (tw.IsSubtree)
			{
				// file/folder conflicts: here I want to detect only file/folder
				// conflict between ours and theirs. file/folder conflicts between
				// base/index/workingTree and something else are not relevant or
				// detected later
				if (NonTree(modeO) && !NonTree(modeT))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0);
					}
					Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				if (NonTree(modeT) && !NonTree(modeO))
				{
					if (NonTree(modeB))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0);
					}
					Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0);
					unmergedPaths.AddItem(tw.PathString);
					enterSubtree = false;
					return true;
				}
				// ours and theirs are both folders or both files (and treewalk
				// tells us we are in a subtree because of index or working-dir).
				// If they are both folders no content-merge is required - we can
				// return here.
				if (!NonTree(modeO))
				{
					return true;
				}
			}
			// ours and theirs are both files, just fall out of the if block
			// and do the content merge
			if (NonTree(modeO) && NonTree(modeT))
			{
				// Check worktree before modifying files
				if (IsWorktreeDirty(work))
				{
					return false;
				}
				// Don't attempt to resolve submodule link conflicts
				if (IsGitLink(modeO) || IsGitLink(modeT))
				{
					Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0);
					Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0);
					Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0);
					unmergedPaths.AddItem(tw.PathString);
					return true;
				}
				MergeResult<RawText> result = ContentMerge(@base, ours, theirs);
				FilePath of = WriteMergedFile(result);
				UpdateIndex(@base, ours, theirs, result, of);
				if (result.ContainsConflicts())
				{
					unmergedPaths.AddItem(tw.PathString);
				}
				modifiedFiles.AddItem(tw.PathString);
			}
			else
			{
				if (modeO != modeT)
				{
					// OURS or THEIRS has been deleted
					if (((modeO != 0 && !tw.IdEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw.IdEqual(T_BASE
						, T_THEIRS))))
					{
						Add(tw.RawPath, @base, DirCacheEntry.STAGE_1, 0, 0);
						Add(tw.RawPath, ours, DirCacheEntry.STAGE_2, 0, 0);
						DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3, 0, 0);
						// OURS was deleted checkout THEIRS
						if (modeO == 0)
						{
							// Check worktree before checking out THEIRS
							if (IsWorktreeDirty(work))
							{
								return false;
							}
							if (NonTree(modeT))
							{
								if (e != null)
								{
									toBeCheckedOut.Put(tw.PathString, e);
								}
							}
						}
						unmergedPaths.AddItem(tw.PathString);
						// generate a MergeResult for the deleted file
						mergeResults.Put(tw.PathString, ContentMerge(@base, ours, theirs).Upcast ());
					}
				}
			}
			return true;
		}
Пример #15
0
 /// <summary>
 /// To set the
 /// <see cref="NGit.Treewalk.WorkingTreeIterator">NGit.Treewalk.WorkingTreeIterator</see>
 /// which should be used. If this
 /// method is not called a standard
 /// <see cref="NGit.Treewalk.FileTreeIterator">NGit.Treewalk.FileTreeIterator</see>
 /// is used.
 /// </summary>
 /// <param name="workingTreeIt">a working tree iterator</param>
 /// <returns>
 ///
 /// <code>this</code>
 /// </returns>
 public virtual NGit.Api.StatusCommand SetWorkingTreeIt(WorkingTreeIterator workingTreeIt
                                                        )
 {
     this.workingTreeIt = workingTreeIt;
     return(this);
 }
Пример #16
0
        /// <summary>
        /// Constructs a DirCacheCeckout for merging and checking out two trees (HEAD
        /// and mergeCommitTree) and the index.
        /// </summary>
        /// <remarks>
        /// Constructs a DirCacheCeckout for merging and checking out two trees (HEAD
        /// and mergeCommitTree) and the index.
        /// </remarks>
        /// <param name="repo">the repository in which we do the checkout</param>
        /// <param name="headCommitTree">the id of the tree of the head commit</param>
        /// <param name="dc">the (already locked) Dircache for this repo</param>
        /// <param name="mergeCommitTree">the id of the tree we want to fast-forward to</param>
        /// <param name="workingTree">an iterator over the repositories Working Tree</param>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        public DirCacheCheckout(Repository repo, ObjectId headCommitTree, DirCache dc, ObjectId
			 mergeCommitTree, WorkingTreeIterator workingTree)
        {
            this.repo = repo;
            this.dc = dc;
            this.headCommitTree = headCommitTree;
            this.mergeCommitTree = mergeCommitTree;
            this.workingTree = workingTree;
        }
Пример #17
0
        /// <summary>
        /// Constructs a DirCacheCeckout for checking out one tree, merging with the
        /// index.
        /// </summary>
        /// <remarks>
        /// Constructs a DirCacheCeckout for checking out one tree, merging with the
        /// index.
        /// </remarks>
        /// <param name="repo">the repository in which we do the checkout</param>
        /// <param name="dc">the (already locked) Dircache for this repo</param>
        /// <param name="mergeCommitTree">the id of the tree we want to fast-forward to</param>
        /// <param name="workingTree">an iterator over the repositories Working Tree</param>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        public DirCacheCheckout(Repository repo, DirCache dc, ObjectId mergeCommitTree, WorkingTreeIterator
			 workingTree)
            : this(repo, null, dc, mergeCommitTree, workingTree)
        {
        }
Пример #18
0
		public override NGit.Api.StatusCommand SetWorkingTreeIt (WorkingTreeIterator workingTreeIt)
		{
			iter = workingTreeIt;
			return this;
		}
Пример #19
0
        /// <summary>Here the main work is done.</summary>
        /// <remarks>
        /// Here the main work is done. This method is called for each existing path
        /// in head, index and merge. This method decides what to do with the
        /// corresponding index entry: keep it, update it, remove it or mark a
        /// conflict.
        /// </remarks>
        /// <param name="h">the entry for the head</param>
        /// <param name="m">the entry for the merge</param>
        /// <param name="i">the entry for the index</param>
        /// <param name="f">the file in the working tree</param>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        internal virtual void ProcessEntry(CanonicalTreeParser h, CanonicalTreeParser m, 
			DirCacheBuildIterator i, WorkingTreeIterator f)
        {
            DirCacheEntry dce = i != null ? i.GetDirCacheEntry() : null;
            string name = walk.PathString;
            if (m != null && !IsValidPath(m))
            {
                throw new InvalidPathException(m.EntryPathString);
            }
            if (i == null && m == null && h == null)
            {
                // File/Directory conflict case #20
                if (walk.IsDirectoryFileConflict())
                {
                    // TODO: check whether it is always correct to report a conflict here
                    Conflict(name, null, null, null);
                }
                // file only exists in working tree -> ignore it
                return;
            }
            ObjectId iId = (i == null ? null : i.EntryObjectId);
            ObjectId mId = (m == null ? null : m.EntryObjectId);
            ObjectId hId = (h == null ? null : h.EntryObjectId);
            FileMode iMode = (i == null ? null : i.EntryFileMode);
            FileMode mMode = (m == null ? null : m.EntryFileMode);
            FileMode hMode = (h == null ? null : h.EntryFileMode);
            // The information whether head,index,merge iterators are currently
            // pointing to file/folder/non-existing is encoded into this variable.
            //
            // To decode write down ffMask in hexadecimal form. The last digit
            // represents the state for the merge iterator, the second last the
            // state for the index iterator and the third last represents the state
            // for the head iterator. The hexadecimal constant "F" stands for
            // "file",
            // an "D" stands for "directory" (tree), and a "0" stands for
            // non-existing
            //
            // Examples:
            // ffMask == 0xFFD -> Head=File, Index=File, Merge=Tree
            // ffMask == 0xDD0 -> Head=Tree, Index=Tree, Merge=Non-Existing
            int ffMask = 0;
            if (h != null)
            {
                ffMask = FileMode.TREE.Equals(hMode) ? unchecked((int)(0xD00)) : unchecked((int)(
                    0xF00));
            }
            if (i != null)
            {
                ffMask |= FileMode.TREE.Equals(iMode) ? unchecked((int)(0x0D0)) : unchecked((int)
                    (0x0F0));
            }
            if (m != null)
            {
                ffMask |= FileMode.TREE.Equals(mMode) ? unchecked((int)(0x00D)) : unchecked((int)
                    (0x00F));
            }
            // Check whether we have a possible file/folder conflict. Therefore we
            // need a least one file and one folder.
            if (((ffMask & unchecked((int)(0x222))) != unchecked((int)(0x000))) && (((ffMask
                & unchecked((int)(0x00F))) == unchecked((int)(0x00D))) || ((ffMask & unchecked((
                int)(0x0F0))) == unchecked((int)(0x0D0))) || ((ffMask & unchecked((int)(0xF00)))
                 == unchecked((int)(0xD00)))))
            {
                switch (ffMask)
                {
                    case unchecked((int)(0xDDF)):
                    {
                        // There are 3*3*3=27 possible combinations of file/folder
                        // conflicts. Some of them are not-relevant because
                        // they represent no conflict, e.g. 0xFFF, 0xDDD, ... The following
                        // switch processes all relevant cases.
                        // 1 2
                        if (IsModified(name))
                        {
                            Conflict(name, dce, h, m);
                        }
                        else
                        {
                            // 1
                            Update(name, mId, mMode);
                        }
                        // 2
                        break;
                    }

                    case unchecked((int)(0xDFD)):
                    {
                        // 3 4
                        // CAUTION: I put it into removed instead of updated, because
                        // that's what our tests expect
                        // updated.put(name, mId);
                        Remove(name);
                        break;
                    }

                    case unchecked((int)(0xF0D)):
                    {
                        // 18
                        Remove(name);
                        break;
                    }

                    case unchecked((int)(0xDFF)):
                    case unchecked((int)(0xFDD)):
                    {
                        // 5 6
                        // 10 11
                        // TODO: make use of tree extension as soon as available in jgit
                        // we would like to do something like
                        // if (!equalIdAndMode(iId, iMode, mId, mMode)
                        //   conflict(name, i.getDirCacheEntry(), h, m);
                        // But since we don't know the id of a tree in the index we do
                        // nothing here and wait that conflicts between index and merge
                        // are found later
                        break;
                    }

                    case unchecked((int)(0xD0F)):
                    {
                        // 19
                        Update(name, mId, mMode);
                        break;
                    }

                    case unchecked((int)(0xDF0)):
                    case unchecked((int)(0x0FD)):
                    {
                        // conflict without a rule
                        // 15
                        Conflict(name, dce, h, m);
                        break;
                    }

                    case unchecked((int)(0xFDF)):
                    {
                        // 7 8 9
                        if (EqualIdAndMode(hId, hMode, mId, mMode))
                        {
                            if (IsModified(name))
                            {
                                Conflict(name, dce, h, m);
                            }
                            else
                            {
                                // 8
                                Update(name, mId, mMode);
                            }
                        }
                        else
                        {
                            // 7
                            if (!IsModified(name))
                            {
                                Update(name, mId, mMode);
                            }
                            else
                            {
                                // 9
                                // To be confirmed - this case is not in the table.
                                Conflict(name, dce, h, m);
                            }
                        }
                        break;
                    }

                    case unchecked((int)(0xFD0)):
                    {
                        // keep without a rule
                        Keep(dce);
                        break;
                    }

                    case unchecked((int)(0xFFD)):
                    {
                        // 12 13 14
                        if (EqualIdAndMode(hId, hMode, iId, iMode))
                        {
                            if (f == null || f.IsModified(dce, true))
                            {
                                Conflict(name, dce, h, m);
                            }
                            else
                            {
                                Remove(name);
                            }
                        }
                        else
                        {
                            Conflict(name, dce, h, m);
                        }
                        break;
                    }

                    case unchecked((int)(0x0DF)):
                    {
                        // 16 17
                        if (!IsModified(name))
                        {
                            Update(name, mId, mMode);
                        }
                        else
                        {
                            Conflict(name, dce, h, m);
                        }
                        break;
                    }

                    default:
                    {
                        Keep(dce);
                        break;
                    }
                }
                return;
            }
            // if we have no file at all then there is nothing to do
            if ((ffMask & unchecked((int)(0x222))) == 0)
            {
                return;
            }
            if ((ffMask == unchecked((int)(0x00F))) && f != null && FileMode.TREE.Equals(f.EntryFileMode
                ))
            {
                // File/Directory conflict case #20
                Conflict(name, null, h, m);
            }
            if (i == null)
            {
                // make sure not to overwrite untracked files
                if (f != null)
                {
                    // A submodule is not a file. We should ignore it
                    if (!FileMode.GITLINK.Equals(mMode))
                    {
                        // a dirty worktree: the index is empty but we have a
                        // workingtree-file
                        if (mId == null || !EqualIdAndMode(mId, mMode, f.EntryObjectId, f.EntryFileMode))
                        {
                            Conflict(name, null, h, m);
                            return;
                        }
                    }
                }
                if (h == null)
                {
                    Update(name, mId, mMode);
                }
                else
                {
                    // 1
                    if (m == null)
                    {
                        Remove(name);
                    }
                    else
                    {
                        // 2
                        Update(name, mId, mMode);
                    }
                }
            }
            else
            {
                // 3
                if (h == null)
                {
                    if (m == null || EqualIdAndMode(mId, mMode, iId, iMode))
                    {
                        if (m == null && walk.IsDirectoryFileConflict())
                        {
                            if (dce != null && (f == null || f.IsModified(dce, true)))
                            {
                                Conflict(name, dce, h, m);
                            }
                            else
                            {
                                Remove(name);
                            }
                        }
                        else
                        {
                            Keep(dce);
                        }
                    }
                    else
                    {
                        Conflict(name, dce, h, m);
                    }
                }
                else
                {
                    if (m == null)
                    {
                        if (iMode == FileMode.GITLINK)
                        {
                            // Submodules that disappear from the checkout must
                            // be removed from the index, but not deleted from disk.
                            Remove(name);
                        }
                        else
                        {
                            if (EqualIdAndMode(hId, hMode, iId, iMode))
                            {
                                if (f == null || f.IsModified(dce, true))
                                {
                                    Conflict(name, dce, h, m);
                                }
                                else
                                {
                                    Remove(name);
                                }
                            }
                            else
                            {
                                Conflict(name, dce, h, m);
                            }
                        }
                    }
                    else
                    {
                        if (!EqualIdAndMode(hId, hMode, mId, mMode) && !EqualIdAndMode(hId, hMode, iId, iMode
                            ) && !EqualIdAndMode(mId, mMode, iId, iMode))
                        {
                            Conflict(name, dce, h, m);
                        }
                        else
                        {
                            if (EqualIdAndMode(hId, hMode, iId, iMode) && !EqualIdAndMode(mId, mMode, iId, iMode
                                ))
                            {
                                // For submodules just update the index with the new SHA-1
                                if (dce != null && FileMode.GITLINK.Equals(dce.FileMode))
                                {
                                    Update(name, mId, mMode);
                                }
                                else
                                {
                                    if (dce != null && (f == null || f.IsModified(dce, true)))
                                    {
                                        Conflict(name, dce, h, m);
                                    }
                                    else
                                    {
                                        Update(name, mId, mMode);
                                    }
                                }
                            }
                            else
                            {
                                Keep(dce);
                            }
                        }
                    }
                }
            }
        }
Пример #20
0
		/// <summary>
		/// Processing an entry in the context of
		/// <see cref="PrescanOneTree()">PrescanOneTree()</see>
		/// when only
		/// one tree is given
		/// </summary>
		/// <param name="m">the tree to merge</param>
		/// <param name="i">the index</param>
		/// <param name="f">the working tree</param>
		/// <exception cref="System.IO.IOException">System.IO.IOException</exception>
		internal virtual void ProcessEntry(CanonicalTreeParser m, DirCacheBuildIterator i
			, WorkingTreeIterator f)
		{
			if (m != null)
			{
				// There is an entry in the merge commit. Means: we want to update
				// what's currently in the index and working-tree to that one
				if (i == null)
				{
					// The index entry is missing
					if (f != null && !FileMode.TREE.Equals(f.EntryFileMode) && !f.IsEntryIgnored())
					{
						// don't overwrite an untracked and not ignored file
						conflicts.AddItem(walk.PathString);
					}
					else
					{
						Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
					}
				}
				else
				{
					if (f == null || !m.IdEqual(i))
					{
						// The working tree file is missing or the merge content differs
						// from index content
						Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
					}
					else
					{
						if (i.GetDirCacheEntry() != null)
						{
							// The index contains a file (and not a folder)
							if (f.IsModified(i.GetDirCacheEntry(), true) || i.GetDirCacheEntry().Stage != 0)
							{
								// The working tree file is dirty or the index contains a
								// conflict
								Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
							}
							else
							{
								Keep(i.GetDirCacheEntry());
							}
						}
						else
						{
							// The index contains a folder
							Keep(i.GetDirCacheEntry());
						}
					}
				}
			}
			else
			{
				// There is no entry in the merge commit. Means: we want to delete
				// what's currently in the index and working tree
				if (f != null)
				{
					// There is a file/folder for that path in the working tree
					if (walk.IsDirectoryFileConflict())
					{
						conflicts.AddItem(walk.PathString);
					}
					else
					{
						// No file/folder conflict exists. All entries are files or
						// all entries are folders
						if (i != null)
						{
							// ... and the working tree contained a file or folder
							// -> add it to the removed set and remove it from
							// conflicts set
							Remove(i.EntryPathString);
							conflicts.Remove(i.EntryPathString);
						}
					}
				}
				else
				{
					// untracked file, neither contained in tree to merge
					// nor in index
					// There is no file/folder for that path in the working tree.
					// The only entry we have is the index entry. If that entry is a
					// conflict simply remove it. Otherwise keep that entry in the
					// index
					if (i.GetDirCacheEntry().Stage == 0)
					{
						Keep(i.GetDirCacheEntry());
					}
				}
			}
		}
Пример #21
0
        /// <summary>Processes one path and tries to merge.</summary>
        /// <remarks>
        /// Processes one path and tries to merge. This method will do all do all
        /// trivial (not content) merges and will also detect if a merge will fail.
        /// The merge will fail when one of the following is true
        /// <ul>
        /// <li>the index entry does not match the entry in ours. When merging one
        /// branch into the current HEAD, ours will point to HEAD and theirs will
        /// point to the other branch. It is assumed that the index matches the HEAD
        /// because it will only not match HEAD if it was populated before the merge
        /// operation. But the merge commit should not accidentally contain
        /// modifications done before the merge. Check the &lt;a href=
        /// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge"
        /// &gt;git read-tree</a> documentation for further explanations.</li>
        /// <li>A conflict was detected and the working-tree file is dirty. When a
        /// conflict is detected the content-merge algorithm will try to write a
        /// merged version into the working-tree. If the file is dirty we would
        /// override unsaved data.</li>
        /// </remarks>
        /// <param name="base">the common base for ours and theirs</param>
        /// <param name="ours">
        /// the ours side of the merge. When merging a branch into the
        /// HEAD ours will point to HEAD
        /// </param>
        /// <param name="theirs">
        /// the theirs side of the merge. When merging a branch into the
        /// current HEAD theirs will point to the branch which is merged
        /// into HEAD.
        /// </param>
        /// <param name="index">the index entry</param>
        /// <param name="work">the file in the working tree</param>
        /// <returns>
        /// <code>false</code> if the merge will fail because the index entry
        /// didn't match ours or the working-dir file was dirty and a
        /// conflict occurred
        /// </returns>
        /// <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>
        private bool ProcessEntry(CanonicalTreeParser @base, CanonicalTreeParser ours, CanonicalTreeParser
			 theirs, DirCacheBuildIterator index, WorkingTreeIterator work)
        {
            enterSubtree = true;
            int modeO = tw.GetRawMode(T_OURS);
            int modeT = tw.GetRawMode(T_THEIRS);
            int modeB = tw.GetRawMode(T_BASE);
            if (modeO == 0 && modeT == 0 && modeB == 0)
            {
                // File is either untracked or new, staged but uncommitted
                return true;
            }
            if (IsIndexDirty())
            {
                return false;
            }
            if (NonTree(modeO) && NonTree(modeT) && tw.IdEqual(T_OURS, T_THEIRS))
            {
                // OURS and THEIRS have equal content. Check the file mode
                if (modeO == modeT)
                {
                    // content and mode of OURS and THEIRS are equal: it doesn't
                    // matter which one we choose. OURS is chosen.
                    Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                    // no checkout needed!
                    return true;
                }
                else
                {
                    // same content but different mode on OURS and THEIRS.
                    // Try to merge the mode and report an error if this is
                    // not possible.
                    int newMode = MergeFileModes(modeB, modeO, modeT);
                    if (newMode != FileMode.MISSING.GetBits())
                    {
                        if (newMode == modeO)
                        {
                            // ours version is preferred
                            Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                        }
                        else
                        {
                            // the preferred version THEIRS has a different mode
                            // than ours. Check it out!
                            if (IsWorktreeDirty())
                            {
                                return false;
                            }
                            DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
                            toBeCheckedOut.Put(tw.PathString, e);
                        }
                        return true;
                    }
                    else
                    {
                        // FileModes are not mergeable. We found a conflict on modes
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                        Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                        Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                        unmergedPaths.AddItem(tw.PathString);
                        mergeResults.Put(tw.PathString, new MergeResult<RawText>(Sharpen.Collections.EmptyList
                            <RawText>()).Upcast ());
                    }
                    return true;
                }
            }
            if (NonTree(modeO) && modeB == modeT && tw.IdEqual(T_BASE, T_THEIRS))
            {
                // THEIRS was not changed compared to BASE. All changes must be in
                // OURS. OURS is chosen.
                Add(tw.RawPath, ours, DirCacheEntry.STAGE_0);
                // no checkout needed!
                return true;
            }
            if (modeB == modeO && tw.IdEqual(T_BASE, T_OURS))
            {
                // OURS was not changed compared to BASE. All changes must be in
                // THEIRS. THEIRS is chosen.
                // Check worktree before checking out THEIRS
                if (IsWorktreeDirty())
                {
                    return false;
                }
                if (NonTree(modeT))
                {
                    DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_0);
                    if (e != null)
                    {
                        toBeCheckedOut.Put(tw.PathString, e);
                    }
                    return true;
                }
                else
                {
                    if (modeT == 0 && modeB != 0)
                    {
                        // we want THEIRS ... but THEIRS contains the deletion of the
                        // file
                        toBeCheckedOut.Put(tw.PathString, null);
                        return true;
                    }
                }
            }
            if (tw.IsSubtree)
            {
                // file/folder conflicts: here I want to detect only file/folder
                // conflict between ours and theirs. file/folder conflicts between
                // base/index/workingTree and something else are not relevant or
                // detected later
                if (NonTree(modeO) && !NonTree(modeT))
                {
                    if (NonTree(modeB))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                    }
                    Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                    unmergedPaths.AddItem(tw.PathString);
                    enterSubtree = false;
                    return true;
                }
                if (NonTree(modeT) && !NonTree(modeO))
                {
                    if (NonTree(modeB))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                    }
                    Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                    unmergedPaths.AddItem(tw.PathString);
                    enterSubtree = false;
                    return true;
                }
                // ours and theirs are both folders or both files (and treewalk
                // tells us we are in a subtree because of index or working-dir).
                // If they are both folders no content-merge is required - we can
                // return here.
                if (!NonTree(modeO))
                {
                    return true;
                }
            }
            // ours and theirs are both files, just fall out of the if block
            // and do the content merge
            if (NonTree(modeO) && NonTree(modeT))
            {
                // Check worktree before modifying files
                if (IsWorktreeDirty())
                {
                    return false;
                }
                MergeResult<RawText> result = ContentMerge(@base, ours, theirs);
                FilePath of = WriteMergedFile(result);
                UpdateIndex(@base, ours, theirs, result, of);
                if (result.ContainsConflicts())
                {
                    unmergedPaths.AddItem(tw.PathString);
                }
                modifiedFiles.AddItem(tw.PathString);
            }
            else
            {
                if (modeO != modeT)
                {
                    // OURS or THEIRS has been deleted
                    if (((modeO != 0 && !tw.IdEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw.IdEqual(T_BASE
                        , T_THEIRS))))
                    {
                        Add(tw.RawPath, @base, DirCacheEntry.STAGE_1);
                        Add(tw.RawPath, ours, DirCacheEntry.STAGE_2);
                        DirCacheEntry e = Add(tw.RawPath, theirs, DirCacheEntry.STAGE_3);
                        // OURS was deleted checkout THEIRS
                        if (modeO == 0)
                        {
                            // Check worktree before checking out THEIRS
                            if (IsWorktreeDirty())
                            {
                                return false;
                            }
                            if (NonTree(modeT))
                            {
                                if (e != null)
                                {
                                    toBeCheckedOut.Put(tw.PathString, e);
                                }
                            }
                        }
                        unmergedPaths.AddItem(tw.PathString);
                        // generate a MergeResult for the deleted file
                        mergeResults.Put(tw.PathString, ContentMerge(@base, ours, theirs).Upcast ());
                    }
                }
            }
            return true;
        }
Пример #22
0
		/// <summary>
		/// Processing an entry in the context of
		/// <see cref="PrescanOneTree()">PrescanOneTree()</see>
		/// when only
		/// one tree is given
		/// </summary>
		/// <param name="m">the tree to merge</param>
		/// <param name="i">the index</param>
		/// <param name="f">the working tree</param>
		internal virtual void ProcessEntry(CanonicalTreeParser m, DirCacheBuildIterator i
			, WorkingTreeIterator f)
		{
			if (m != null)
			{
				if (i == null || f == null || !m.IdEqual(i) || (i.GetDirCacheEntry() != null && (
					f.IsModified(i.GetDirCacheEntry(), true) || i.GetDirCacheEntry().Stage != 0)))
				{
					Update(m.EntryPathString, m.EntryObjectId, m.EntryFileMode);
				}
				else
				{
					Keep(i.GetDirCacheEntry());
				}
			}
			else
			{
				if (f != null)
				{
					if (walk.IsDirectoryFileConflict())
					{
						conflicts.AddItem(walk.PathString);
					}
					else
					{
						if (i != null)
						{
							// ... and the working dir contained a file or folder ->
							// add it to the removed set and remove it from
							// conflicts set
							Remove(i.EntryPathString);
							conflicts.Remove(i.EntryPathString);
						}
					}
				}
				else
				{
					if (i.GetDirCacheEntry().Stage == 0)
					{
						Keep(i.GetDirCacheEntry());
					}
				}
			}
		}
Пример #23
0
		protected internal override byte[] IdSubmodule(WorkingTreeIterator.Entry e)
		{
			if (repository == null)
			{
				return IdSubmodule(GetDirectory(), e);
			}
			return base.IdSubmodule(e);
		}
Пример #24
0
			internal WorkingTreeSource(WorkingTreeIterator iterator)
			{
				this.tw = new TreeWalk((ObjectReader)null);
				this.iterator = iterator;
			}
Пример #25
0
		/// <summary>Sets the WorkingTreeIterator to be used by this merger.</summary>
		/// <remarks>
		/// Sets the WorkingTreeIterator to be used by this merger. If no
		/// WorkingTreeIterator is set this merger will ignore the working tree and
		/// fail if a content merge is necessary.
		/// <p>
		/// TODO: enhance WorkingTreeIterator to support write operations. Then this
		/// merger will be able to merge with a different working tree abstraction.
		/// </remarks>
		/// <param name="workingTreeIterator">the workingTreeIt to set</param>
		public virtual void SetWorkingTreeIterator(WorkingTreeIterator workingTreeIterator
			)
		{
			this.workingTreeIterator = workingTreeIterator;
		}
Пример #26
0
 /// <summary>Allow clients to provide their own implementation of a FileTreeIterator</summary>
 /// <param name="f"></param>
 /// <returns>
 ///
 /// <code>this</code>
 /// </returns>
 public virtual NGit.Api.AddCommand SetWorkingTreeIterator(WorkingTreeIterator f)
 {
     workingTreeIterator = f;
     return(this);
 }