Example usage for org.eclipse.jgit.merge MergeResult MergeResult

List of usage examples for org.eclipse.jgit.merge MergeResult MergeResult

Introduction

In this page you can find the example usage for org.eclipse.jgit.merge MergeResult MergeResult.

Prototype

public MergeResult(List<S> sequences) 

Source Link

Document

Creates a new empty MergeResult

Usage

From source file:com.itemis.maven.plugins.unleash.scm.providers.merge.UnleashGitMerger.java

License:Eclipse Distribution License

/**
 * 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>/*w ww.  ja  va2s.  c o  m*/
 * <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>
 * </ul>
 *
 * @param base
 *          the common base for ours and theirs
 * @param ours
 *          the ours side of the merge. When merging a branch into the
 *          HEAD ours will point to HEAD
 * @param 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 index
 *          the index entry
 * @param work
 *          the file in the working tree
 * @param ignoreConflicts
 *          see
 *          {@link UnleashGitMerger#mergeTrees(AbstractTreeIterator, RevTree, RevTree, boolean)}
 * @return <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
 * @throws MissingObjectException
 * @throws IncorrectObjectTypeException
 * @throws CorruptObjectException
 * @throws IOException
 * @since 3.5
 */
@Override
protected boolean processEntry(CanonicalTreeParser base, CanonicalTreeParser ours, CanonicalTreeParser theirs,
        DirCacheBuildIterator index, WorkingTreeIterator work, boolean ignoreConflicts)
        throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException {
    this.enterSubtree = true;
    final int modeO = this.tw.getRawMode(T_OURS);
    final int modeT = this.tw.getRawMode(T_THEIRS);
    final int modeB = this.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(this.tw.getRawPath());
            ourDce.setObjectId(this.tw.getObjectId(T_OURS));
            ourDce.setFileMode(this.tw.getFileMode(T_OURS));
        }
    } else {
        ourDce = index.getDirCacheEntry();
    }

    if (nonTree(modeO) && nonTree(modeT) && this.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, ourDce)) {
                        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(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_0, 0, 0);
                    this.toBeCheckedOut.put(this.tw.getPathString(), 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(this.tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
                add(this.tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
                add(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
                this.unmergedPaths.add(this.tw.getPathString());
                this.mergeResults.put(this.tw.getPathString(),
                        new MergeResult<RawText>(Collections.<RawText>emptyList()));
            }
            return true;
        }
    }

    if (modeB == modeT && this.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.
        if (ourDce != null) {
            keep(ourDce);
        }
        // no checkout needed!
        return true;
    }

    if (modeB == modeO && this.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, ourDce)) {
            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(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_0, 0, 0);
            if (e != null) {
                this.toBeCheckedOut.put(this.tw.getPathString(), e);
            }
            return true;
        } else {
            // we want THEIRS ... but THEIRS contains a folder or the
            // deletion of the path. Delete what's in the workingtree (the
            // workingtree is clean) but do not complain if the file is
            // already deleted locally. This complements the test in
            // isWorktreeDirty() for the same case.
            if (this.tw.getTreeCount() > T_FILE && this.tw.getRawMode(T_FILE) == 0) {
                return true;
            }
            this.toBeDeleted.add(this.tw.getPathString());
            return true;
        }
    }

    if (this.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(this.tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
            }
            add(this.tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
            this.unmergedPaths.add(this.tw.getPathString());
            this.enterSubtree = false;
            return true;
        }
        if (nonTree(modeT) && !nonTree(modeO)) {
            if (nonTree(modeB)) {
                add(this.tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
            }
            add(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
            this.unmergedPaths.add(this.tw.getPathString());
            this.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, ourDce)) {
            return false;
        }

        // Don't attempt to resolve submodule link conflicts
        if (isGitLink(modeO) || isGitLink(modeT)) {
            add(this.tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
            add(this.tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
            add(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
            this.unmergedPaths.add(this.tw.getPathString());
            return true;
        }

        MergeResult<RawText> result = contentMerge(base, ours, theirs);
        // if (ignoreConflicts) {
        // result.setContainsConflicts(false);
        // }
        updateIndex(base, ours, theirs, result);
        if (result.containsConflicts() && !ignoreConflicts) {
            this.unmergedPaths.add(this.tw.getPathString());
        }
        this.modifiedFiles.add(this.tw.getPathString());
    } else if (modeO != modeT) {
        // OURS or THEIRS has been deleted
        if (modeO != 0 && !this.tw.idEqual(T_BASE, T_OURS)
                || modeT != 0 && !this.tw.idEqual(T_BASE, T_THEIRS)) {

            add(this.tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
            add(this.tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
            DirCacheEntry e = add(this.tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);

            // OURS was deleted checkout THEIRS
            if (modeO == 0) {
                // Check worktree before checking out THEIRS
                if (isWorktreeDirty(work, ourDce)) {
                    return false;
                }
                if (nonTree(modeT)) {
                    if (e != null) {
                        this.toBeCheckedOut.put(this.tw.getPathString(), e);
                    }
                }
            }

            this.unmergedPaths.add(this.tw.getPathString());

            // generate a MergeResult for the deleted file
            this.mergeResults.put(this.tw.getPathString(), contentMerge(base, ours, theirs));
        }
    }
    return true;
}

From source file:com.itemis.maven.plugins.unleash.scm.providers.merge.UnleashGitMerger.java

License:Eclipse Distribution License

private MergeResult<RawText> contentMerge(CanonicalTreeParser base, CanonicalTreeParser ours,
        CanonicalTreeParser theirs) throws IOException {
    InputStream localIn = getInputStream(ours.getEntryObjectId());
    InputStream remoteIn = getInputStream(theirs.getEntryObjectId());
    InputStream baseIn = getInputStream(base.getEntryObjectId());
    ByteArrayOutputStream resultOut = new ByteArrayOutputStream();

    this.mergeClient.merge(localIn, remoteIn, baseIn, resultOut);
    RawText resultText = new RawText(resultOut.toByteArray());

    List<RawText> sequences = new ArrayList<RawText>(1);
    sequences.add(resultText);//ww w.ja  v a 2  s.c o  m
    MergeResult<RawText> result = new MergeResult<RawText>(sequences);
    result.add(0, 0, resultText.size(), ConflictState.NO_CONFLICT);

    return result;
}