/// <exception cref="System.Exception"></exception> private DirCacheEntry MakeEntry(string path, FileMode mode) { DirCacheEntry ent = new DirCacheEntry(path); ent.FileMode = mode; ent.SetObjectId(new ObjectInserter.Formatter().IdFor(Constants.OBJ_BLOB, Constants .Encode(path))); return(ent); }
/// <summary> /// adds a entry to the index builder which is a copy of the specified /// DirCacheEntry /// </summary> /// <param name="e">the entry which should be copied</param> /// <returns>the entry which was added to the index</returns> private DirCacheEntry Keep(DirCacheEntry e) { DirCacheEntry newEntry = new DirCacheEntry(e.PathString, e.Stage); newEntry.FileMode = e.FileMode; newEntry.SetObjectId(e.GetObjectId()); newEntry.LastModified = e.LastModified; newEntry.SetLength(e.Length); builder.Add(newEntry); return(newEntry); }
public override void Apply(DirCacheEntry ent) { ent.SetObjectId(blobId); ent.FileMode = mode; try { DirCacheCheckout.CheckoutEntry(this._enclosing.repo, new FilePath(workTree, ent.PathString ), ent, r); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().checkoutConflictWithFile , ent.PathString), e); } }
/// <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); } } }
private void ResetIndexForPaths(RevCommit commit) { DirCache dc = null; try { dc = repo.LockDirCache(); DirCacheBuilder builder = dc.Builder(); TreeWalk tw = new TreeWalk(repo); tw.AddTree(new DirCacheBuildIterator(builder)); tw.AddTree(commit.Tree); tw.Filter = PathFilterGroup.CreateFromStrings(filepaths); tw.Recursive = true; while (tw.Next()) { CanonicalTreeParser tree = tw.GetTree <CanonicalTreeParser>(1); // only keep file in index if it's in the commit if (tree != null) { // revert index to commit DirCacheEntry entry = new DirCacheEntry(tw.RawPath); entry.FileMode = tree.EntryFileMode; entry.SetObjectId(tree.EntryObjectId); builder.Add(entry); } } builder.Commit(); } catch (IOException e) { throw new RuntimeException(e); } finally { if (dc != null) { dc.Unlock(); } } }
public override void Apply(DirCacheEntry ent) { if (checkoutIndex && ent.Stage > DirCacheEntry.STAGE_0) { UnmergedPathException e = new UnmergedPathException(ent); throw new JGitInternalException(e.Message, e); } ent.SetObjectId(blobId); ent.FileMode = mode; FilePath file = new FilePath(workTree, ent.PathString); FilePath parentDir = file.GetParentFile(); try { FileUtils.Mkdirs(parentDir, true); DirCacheCheckout.CheckoutEntry(this._enclosing.repo, file, ent, r); } catch (IOException e) { throw new JGitInternalException(MessageFormat.Format(JGitText.Get().checkoutConflictWithFile , ent.PathString), e); } }
/// <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 <a href= /// "http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html#_3_way_merge" /// >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); }
public override void Apply(DirCacheEntry ent) { ent.FileMode = FileMode.REGULAR_FILE; ent.SetLength(f.Length()); ent.SetObjectId(id); }
public override void Apply(DirCacheEntry ent) { ent.FileMode = FileMode.REGULAR_FILE; ent.SetObjectId(id); ent.IsUpdateNeeded = false; }
public override void Apply(DirCacheEntry ent) { ent.SetObjectId(blobId); }