Example usage for org.eclipse.jgit.dircache DirCacheEntry STAGE_2

List of usage examples for org.eclipse.jgit.dircache DirCacheEntry STAGE_2

Introduction

In this page you can find the example usage for org.eclipse.jgit.dircache DirCacheEntry STAGE_2.

Prototype

int STAGE_2

To view the source code for org.eclipse.jgit.dircache DirCacheEntry STAGE_2.

Click Source Link

Document

The first tree revision (usually called "ours").

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  w w .jav  a  2  s  . 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

/**
 * Updates the index after a content merge has happened. If no conflict has
 * occurred this includes persisting the merged content to the object
 * database. In case of conflicts this method takes care to write the
 * correct stages to the index.//from w w  w. j a  va2s  .  c  o  m
 *
 * @param base
 * @param ours
 * @param theirs
 * @param result
 * @throws FileNotFoundException
 * @throws IOException
 */
private void updateIndex(CanonicalTreeParser base, CanonicalTreeParser ours, CanonicalTreeParser theirs,
        MergeResult<RawText> result) throws FileNotFoundException, IOException {
    File mergedFile = !this.inCore ? writeMergedFile(result) : null;
    if (result.containsConflicts()) {
        // A conflict occurred, the file will contain conflict markers
        // the index will be populated with the three stages and the
        // workdir (if used) contains the halfway merged content.
        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.mergeResults.put(this.tw.getPathString(), result);
        return;
    }

    // No conflict occurred, the file will contain fully merged content.
    // The index will be populated with the new merged version.
    DirCacheEntry dce = new DirCacheEntry(this.tw.getPathString());

    // Set the mode for the new content. Fall back to REGULAR_FILE if
    // we can't merge modes of OURS and THEIRS.
    int newMode = mergeFileModes(this.tw.getRawMode(0), this.tw.getRawMode(1), this.tw.getRawMode(2));
    dce.setFileMode(newMode == FileMode.MISSING.getBits() ? FileMode.REGULAR_FILE : FileMode.fromBits(newMode));
    if (mergedFile != null) {
        long len = mergedFile.length();
        dce.setLastModified(mergedFile.lastModified());
        dce.setLength((int) len);
        InputStream is = new FileInputStream(mergedFile);
        try {
            dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is));
        } finally {
            is.close();
        }
    } else {
        dce.setObjectId(insertMergeResult(result));
    }
    this.builder.add(dce);
}

From source file:org.eclipse.egit.core.GitMoveDeleteHookTest.java

License:Open Source License

private static void addUnmergedEntry(String filePath, DirCacheBuilder builder) {
    DirCacheEntry stage1 = new DirCacheEntry(filePath, DirCacheEntry.STAGE_1);
    DirCacheEntry stage2 = new DirCacheEntry(filePath, DirCacheEntry.STAGE_2);
    DirCacheEntry stage3 = new DirCacheEntry(filePath, DirCacheEntry.STAGE_3);
    stage1.setFileMode(FileMode.REGULAR_FILE);
    stage2.setFileMode(FileMode.REGULAR_FILE);
    stage3.setFileMode(FileMode.REGULAR_FILE);
    builder.add(stage1);/*  w w w  .  ja  v  a  2s . co m*/
    builder.add(stage2);
    builder.add(stage3);
}

From source file:org.eclipse.egit.core.internal.merge.DirCacheResourceVariantTreeProvider.java

License:Open Source License

/**
 * Constructs the resource variant trees by iterating over the given
 * repository's DirCache entries./*  w w w  .j ava  2  s  .  c  om*/
 *
 * @param repository
 *            The repository which DirCache info we need to cache as
 *            IResourceVariantTrees.
 * @throws IOException
 *             if we somehow cannot read the DirCache.
 */
public DirCacheResourceVariantTreeProvider(Repository repository) throws IOException {
    final DirCache cache = repository.readDirCache();
    final GitResourceVariantCache baseCache = new GitResourceVariantCache();
    final GitResourceVariantCache sourceCache = new GitResourceVariantCache();
    final GitResourceVariantCache remoteCache = new GitResourceVariantCache();

    for (int i = 0; i < cache.getEntryCount(); i++) {
        final DirCacheEntry entry = cache.getEntry(i);
        final IPath path = new Path(entry.getPathString());
        final IResource resource = ResourceUtil.getResourceHandleForLocation(path);
        // Resource variants only make sense for IResources. Do not consider
        // files outside of the workspace or otherwise non accessible.
        if (resource == null || resource.getProject() == null || !resource.getProject().isAccessible()) {
            continue;
        }
        switch (entry.getStage()) {
        case DirCacheEntry.STAGE_0:
            // Skipped on purpose (no conflict)
            break;
        case DirCacheEntry.STAGE_1:
            baseCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        case DirCacheEntry.STAGE_2:
            sourceCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        case DirCacheEntry.STAGE_3:
            remoteCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        default:
            throw new IllegalStateException("Invalid stage: " + entry.getStage()); //$NON-NLS-1$
        }
    }

    baseTree = new GitCachedResourceVariantTree(baseCache);
    sourceTree = new GitCachedResourceVariantTree(sourceCache);
    remoteTree = new GitCachedResourceVariantTree(remoteCache);

    roots = new LinkedHashSet<IResource>();
    roots.addAll(baseCache.getRoots());
    roots.addAll(sourceCache.getRoots());
    roots.addAll(remoteCache.getRoots());

    knownResources = new LinkedHashSet<IResource>();
    knownResources.addAll(baseCache.getKnownResources());
    knownResources.addAll(sourceCache.getKnownResources());
    knownResources.addAll(remoteCache.getKnownResources());
}

From source file:org.eclipse.egit.core.internal.merge.ResourceVariantTest.java

License:Open Source License

@Test
public void testIndexVariantsConflict() throws Exception {
    File file1 = testRepo.createFile(iProject, "file1");
    IFile iFile1 = testRepo.getIFile(iProject, file1);

    setupConflictingBranches();/*  w  ww .j a  va  2 s .c o  m*/
    // end setup

    // create a conflict to force multiple stages
    new MergeOperation(repo, BRANCH).execute(null);

    DirCache cache = repo.readDirCache();
    // 3 stages for file 1, 2 stages for file 2
    assertEquals(5, cache.getEntryCount());
    for (int i = 0; i < cache.getEntryCount(); i++) {
        final DirCacheEntry entry = cache.getEntry(i);

        AbstractGitResourceVariant variant = IndexResourceVariant.create(repo, entry);
        assertEquals(entry.getObjectId().getName(), variant.getContentIdentifier());
        assertEquals(entry.getObjectId(), variant.getObjectId());
        assertEquals(entry.getRawMode(), variant.getRawMode());
        if (iFile1.getName().equals(variant.getName())) {
            switch (entry.getStage()) {
            case DirCacheEntry.STAGE_1:
                assertContentEquals(variant, INITIAL_CONTENT_1);
                break;
            case DirCacheEntry.STAGE_2:
                assertContentEquals(variant, INITIAL_CONTENT_1 + MASTER_CHANGE);
                break;
            case DirCacheEntry.STAGE_3:
                assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_1);
                break;
            case DirCacheEntry.STAGE_0:
            default:
                fail("Unexpected entry stage " + entry.getStage() + " in the index for file "
                        + entry.getPathString());
                break;
            }
        } else {
            switch (entry.getStage()) {
            case DirCacheEntry.STAGE_2:
                assertContentEquals(variant, INITIAL_CONTENT_2 + MASTER_CHANGE);
                break;
            case DirCacheEntry.STAGE_3:
                assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_2);
                break;
            case DirCacheEntry.STAGE_0:
            case DirCacheEntry.STAGE_1:
            default:
                fail("Unexpected entry stage " + entry.getStage() + " in the index for file "
                        + entry.getPathString());
                break;
            }
        }
    }
}

From source file:org.eclipse.emf.compare.egit.internal.merge.DirCacheResourceVariantTreeProvider.java

License:Open Source License

/**
 * Constructs the resource variant trees by iterating over the given repository's DirCache entries.
 *
 * @param repository//from  w w w  .  ja  v a 2 s. co  m
 *            The repository which DirCache info we need to cache as IResourceVariantTrees.
 * @param useWorkspace
 *            Whether we should use local data instead of what's in the index for our side.
 * @throws IOException
 *             if we somehow cannot read the DirCache.
 */
public DirCacheResourceVariantTreeProvider(Repository repository, boolean useWorkspace) throws IOException {
    final DirCache cache = repository.readDirCache();
    final GitResourceVariantCache baseCache = new GitResourceVariantCache();
    final GitResourceVariantCache sourceCache = new GitResourceVariantCache();
    final GitResourceVariantCache remoteCache = new GitResourceVariantCache();

    for (int i = 0; i < cache.getEntryCount(); i++) {
        final DirCacheEntry entry = cache.getEntry(i);
        final IResource resource = ModelEGitResourceUtil.getResourceHandleForLocation(repository,
                entry.getPathString(), FileMode.fromBits(entry.getRawMode()) == FileMode.TREE);
        // Resource variants only make sense for IResources. Do not consider
        // files outside of the workspace or otherwise non accessible.
        if (resource == null || resource.getProject() == null || !resource.getProject().isAccessible()) {
            continue;
        }
        switch (entry.getStage()) {
        case DirCacheEntry.STAGE_0:
            if (useWorkspace) {
                sourceCache.setVariant(resource, new GitLocalResourceVariant(resource));
            } else {
                sourceCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            }
            baseCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            remoteCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        case DirCacheEntry.STAGE_1:
            baseCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        case DirCacheEntry.STAGE_2:
            if (useWorkspace) {
                sourceCache.setVariant(resource, new GitLocalResourceVariant(resource));
            } else {
                sourceCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            }
            break;
        case DirCacheEntry.STAGE_3:
            remoteCache.setVariant(resource, IndexResourceVariant.create(repository, entry));
            break;
        default:
            throw new IllegalStateException("Invalid stage: " + entry.getStage()); //$NON-NLS-1$
        }
    }

    baseTree = new GitCachedResourceVariantTree(baseCache);
    sourceTree = new GitCachedResourceVariantTree(sourceCache);
    remoteTree = new GitCachedResourceVariantTree(remoteCache);

    roots = new LinkedHashSet<IResource>();
    roots.addAll(baseCache.getRoots());
    roots.addAll(sourceCache.getRoots());
    roots.addAll(remoteCache.getRoots());

    knownResources = new LinkedHashSet<IResource>();
    knownResources.addAll(baseCache.getKnownResources());
    knownResources.addAll(sourceCache.getKnownResources());
    knownResources.addAll(remoteCache.getKnownResources());
}

From source file:org.eclipse.emf.compare.egit.internal.merge.RecursiveModelMerger.java

License:Open Source License

private void markConflict(String filePath, DirCacheBuilder cacheBuilder, TreeParserResourceVariant baseVariant,
        TreeParserResourceVariant ourVariant, TreeParserResourceVariant theirVariant) {
    add(filePath, cacheBuilder, baseVariant, DirCacheEntry.STAGE_1);
    add(filePath, cacheBuilder, ourVariant, DirCacheEntry.STAGE_2);
    add(filePath, cacheBuilder, theirVariant, DirCacheEntry.STAGE_3);
}

From source file:org.eclipse.emf.compare.egit.ui.internal.merge.ModelGitMergeEditorInput.java

License:Open Source License

private IDiffContainer buildDiffContainer(Repository repository, RevCommit headCommit, RevCommit ancestorCommit,
        List<String> filterPaths, RevWalk rw, IProgressMonitor monitor)
        throws IOException, InterruptedException {

    monitor.setTaskName(UIText.GitMergeEditorInput_CalculatingDiffTaskName);
    IDiffContainer result = new DiffNode(Differencer.CONFLICTING);

    TreeWalk tw = new TreeWalk(repository);
    try {/*from  w w w.j  a  v  a 2s . c  om*/
        int dirCacheIndex = tw.addTree(new DirCacheIterator(repository.readDirCache()));
        int fileTreeIndex = tw.addTree(new FileTreeIterator(repository));
        int repositoryTreeIndex = tw.addTree(rw.parseTree(repository.resolve(Constants.HEAD)));

        // skip ignored resources
        NotIgnoredFilter notIgnoredFilter = new NotIgnoredFilter(fileTreeIndex);
        // filter by selected resources
        if (filterPaths.size() > 1) {
            List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
            for (String filterPath : filterPaths) {
                suffixFilters.add(PathFilter.create(filterPath));
            }
            TreeFilter otf = OrTreeFilter.create(suffixFilters);
            tw.setFilter(AndTreeFilter.create(otf, notIgnoredFilter));
        } else if (filterPaths.size() > 0) {
            String path = filterPaths.get(0);
            if (path.length() == 0) {
                tw.setFilter(notIgnoredFilter);
            } else {
                tw.setFilter(AndTreeFilter.create(PathFilter.create(path), notIgnoredFilter));
            }
        } else {
            tw.setFilter(notIgnoredFilter);
        }

        tw.setRecursive(true);

        while (tw.next()) {
            if (monitor.isCanceled()) {
                throw new InterruptedException();
            }
            String gitPath = tw.getPathString();
            monitor.setTaskName(gitPath);

            FileTreeIterator fit = tw.getTree(fileTreeIndex, FileTreeIterator.class);
            if (fit == null) {
                continue;
            }

            DirCacheIterator dit = tw.getTree(dirCacheIndex, DirCacheIterator.class);

            final DirCacheEntry dirCacheEntry = dit == null ? null : dit.getDirCacheEntry();

            boolean conflicting = dirCacheEntry != null && dirCacheEntry.getStage() > 0;

            AbstractTreeIterator rt = tw.getTree(repositoryTreeIndex, AbstractTreeIterator.class);

            // compare local file against HEAD to see if it was modified
            boolean modified = rt != null && !fit.getEntryObjectId().equals(rt.getEntryObjectId());

            // if this is neither conflicting nor changed, we skip it
            if (!conflicting && !modified) {
                continue;
            }

            ITypedElement right;
            if (conflicting) {
                GitFileRevision revision = GitFileRevision.inIndex(repository, gitPath, DirCacheEntry.STAGE_3);
                String encoding = CompareCoreUtils.getResourceEncoding(repository, gitPath);
                right = new FileRevisionTypedElement(revision, encoding);
            } else {
                right = CompareUtils.getFileRevisionTypedElement(gitPath, headCommit, repository);
            }

            // can this really happen?
            if (right instanceof EmptyTypedElement) {
                continue;
            }

            IFileRevision rev;
            // if the file is not conflicting (as it was auto-merged)
            // we will show the auto-merged (local) version

            Path repositoryPath = new Path(repository.getWorkTree().getAbsolutePath());
            IPath location = repositoryPath.append(fit.getEntryPathString());
            IFile file = ResourceUtil.getFileForLocation(location, false);
            if (!conflicting || useWorkspace) {
                if (file != null) {
                    rev = new LocalFileRevision(file);
                } else {
                    rev = new WorkingTreeFileRevision(location.toFile());
                }
            } else {
                rev = GitFileRevision.inIndex(repository, gitPath, DirCacheEntry.STAGE_2);
            }

            IRunnableContext runnableContext = getContainer();
            if (runnableContext == null) {
                runnableContext = PlatformUI.getWorkbench().getProgressService();
            }

            EditableRevision leftEditable;
            if (file != null) {
                leftEditable = new ResourceEditableRevision(rev, file, runnableContext);
            } else {
                leftEditable = new LocationEditableRevision(rev, location, runnableContext);
            }
            // make sure we don't need a round trip later
            try {
                leftEditable.cacheContents(monitor);
            } catch (CoreException e) {
                throw new IOException(e.getMessage());
            }

            int kind = Differencer.NO_CHANGE;
            if (conflicting) {
                kind = Differencer.CONFLICTING;
            } else if (modified) {
                kind = Differencer.PSEUDO_CONFLICT;
            }

            IDiffContainer fileParent = getFileParent(result, repositoryPath, file, location);

            ITypedElement anc;
            if (ancestorCommit != null) {
                anc = CompareUtils.getFileRevisionTypedElement(gitPath, ancestorCommit, repository);
            } else {
                anc = null;
            }
            // we get an ugly black icon if we have an EmptyTypedElement
            // instead of null
            if (anc instanceof EmptyTypedElement) {
                anc = null;
            }
            // create the node as child
            new DiffNode(fileParent, kind, anc, leftEditable, right);
        }
        return result;
    } finally {
        tw.close();
    }
}

From source file:org.eclipse.emf.compare.ide.ui.tests.merge.ResourceVariantTest.java

License:Open Source License

@Test
public void testIndexVariantsConflict() throws Exception {
    File file1 = repository.createFile(iProject, "file1");
    IFile iFile1 = repository.getIFile(iProject, file1);

    setupConflictingBranches();/*from   w w w  .  j ava  2  s.  c  om*/
    // end setup

    // create a conflict to force multiple stages
    new MergeOperation(repo, BRANCH).execute(null);

    DirCache cache = repo.readDirCache();
    // 3 stages for file 1, 2 stages for file 2
    assertEquals(5, cache.getEntryCount());
    for (int i = 0; i < cache.getEntryCount(); i++) {
        final DirCacheEntry entry = cache.getEntry(i);

        AbstractGitResourceVariant variant = IndexResourceVariant.create(repo, entry);
        assertEquals(entry.getObjectId().getName(), variant.getContentIdentifier());
        assertEquals(entry.getObjectId(), variant.getObjectId());
        assertEquals(entry.getRawMode(), variant.getRawMode());
        if (iFile1.getName().equals(variant.getName())) {
            switch (entry.getStage()) {
            case DirCacheEntry.STAGE_1:
                assertContentEquals(variant, INITIAL_CONTENT_1);
                break;
            case DirCacheEntry.STAGE_2:
                assertContentEquals(variant, INITIAL_CONTENT_1 + MASTER_CHANGE);
                break;
            case DirCacheEntry.STAGE_3:
                assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_1);
                break;
            case DirCacheEntry.STAGE_0:
            default:
                fail("Unexpected entry stage " + entry.getStage() + " in the index for file "
                        + entry.getPathString());
                break;
            }
        } else {
            switch (entry.getStage()) {
            case DirCacheEntry.STAGE_2:
                assertContentEquals(variant, INITIAL_CONTENT_2 + MASTER_CHANGE);
                break;
            case DirCacheEntry.STAGE_3:
                assertContentEquals(variant, BRANCH_CHANGE + INITIAL_CONTENT_2);
                break;
            case DirCacheEntry.STAGE_0:
            case DirCacheEntry.STAGE_1:
            default:
                fail("Unexpected entry stage " + entry.getStage() + " in the index for file "
                        + entry.getPathString());
                break;
            }
        }
    }
}

From source file:org.openflexo.hannah.IterativeFileGenerator.java

License:Open Source License

/**
 * <p>Ends the generation. It asks to resolve conflicts (if any). By 
 * default conflict are resolved using user modifications.</p>
 * @param callback callback to handle conflicts
 * @throws IOException//w w  w.  j  av a 2  s .  c om
 */
public void end(ConflictHandler callback) throws IOException, GitAPIException {
    final Status status = git.status().call();

    // checks if needs commit.
    if (status.isClean() == false) {

        // checks for files to add
        boolean execute = false;
        final AddCommand add = git.add();
        for (String filename : status.getModified()) {
            execute = true;
            add.addFilepattern(filename);
        }

        for (String filename : status.getUntracked()) {
            execute = true;
            add.addFilepattern(filename);
        }
        if (execute)
            add.call();

        // checks for files to remove
        execute = false;
        final RmCommand rm = git.rm();
        for (String filename : status.getMissing()) {
            execute = true;
            rm.addFilepattern(filename);
        }
        if (execute)
            rm.call();

        git.commit().setMessage("Generation").call();
    }

    // checks out master branch
    git.checkout().setName(MASTER).call();

    // merges generation branch with master (resolving conflict with USER).
    final Repository repo = git.getRepository();
    final Ref generationHead = repo.getRef(GENERATION);
    final MergeStatus mergeStatus = git.merge().include(generationHead).call().getMergeStatus();

    // in case of conflicts, uses the resolution mode to choose the outcome
    if (mergeStatus == MergeStatus.CONFLICTING) {
        // maps to stores confliting files
        final Map<String, DirCacheEntry> baseEntry = new LinkedHashMap<String, DirCacheEntry>();
        final Map<String, DirCacheEntry> userEntry = new LinkedHashMap<String, DirCacheEntry>();
        final Map<String, DirCacheEntry> generationEntry = new LinkedHashMap<String, DirCacheEntry>();

        // for all conflicting entry collects base, user and generation entries. 
        final DirCache cache = repo.lockDirCache();
        for (int i = 0; i < cache.getEntryCount(); i++) {
            final DirCacheEntry entry = cache.getEntry(i);
            switch (entry.getStage()) {
            case DirCacheEntry.STAGE_1:
                baseEntry.put(entry.getPathString(), entry);
                break;
            case DirCacheEntry.STAGE_2:
                userEntry.put(entry.getPathString(), entry);
                break;
            case DirCacheEntry.STAGE_3:
                generationEntry.put(entry.getPathString(), entry);
                break;
            }
        }

        // creates list of conflicting files
        final List<ConflictingFile> conflictingFiles = new ArrayList<ConflictingFile>();
        final MergeAlgorithm mergeAlgorithm = new MergeAlgorithm();
        for (final String path : baseEntry.keySet()) {
            final RawText baseText = getRawText(baseEntry.get(path));
            final RawText userText = getRawText(userEntry.get(path));
            final RawText generationText = getRawText(generationEntry.get(path));

            final MergeResult<RawText> result = mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText,
                    userText, generationText);
            conflictingFiles.add(new ConflictingFile(path, result));

        }
        // unlocks cache.
        cache.unlock();

        // calls the callback
        callback.conflicts(conflictingFiles);

        // prepares the reset command
        final ResetCommand reset = git.reset();

        // applies callback selections
        for (final ConflictingFile conflictingFile : conflictingFiles) {
            final File file = new File(repo.getWorkTree(), conflictingFile.getPath());
            FileUtil.writeFile(file, conflictingFile.getContents(), "UTF-8");

            reset.addPath(conflictingFile.getPath());
        }

        // resets repository state to allows commit.
        reset.call();

        // commit resolutions
        git.commit().setMessage("User/Generation merge conflicts resolutions.").call();
    }

    // renames git repository to hannah
    gitFolder.renameTo(hannahFolder);
}