Search in sources :

Example 6 with DirCacheEntry

use of org.eclipse.jgit.dircache.DirCacheEntry in project gerrit by GerritCodeReview.

the class AutoMerger method merge.

/**
   * Perform an auto-merge of the parents of the given merge commit.
   *
   * @return auto-merge commit or {@code null} if an auto-merge commit couldn't be created. Headers
   *     of the returned RevCommit are parsed.
   */
public RevCommit merge(Repository repo, RevWalk rw, final ObjectInserter ins, RevCommit merge, ThreeWayMergeStrategy mergeStrategy) throws IOException {
    checkArgument(rw.getObjectReader().getCreatedFromInserter() == ins);
    InMemoryInserter tmpIns = null;
    if (ins instanceof InMemoryInserter) {
        // Caller gave us an in-memory inserter, so ensure anything we write from
        // this method is visible to them.
        tmpIns = (InMemoryInserter) ins;
    } else if (!save) {
        // If we don't plan on saving results, use a fully in-memory inserter.
        // Using just a non-flushing wrapper is not sufficient, since in
        // particular DfsInserter might try to write to storage after exceeding an
        // internal buffer size.
        tmpIns = new InMemoryInserter(rw.getObjectReader());
    }
    rw.parseHeaders(merge);
    String refName = RefNames.refsCacheAutomerge(merge.name());
    Ref ref = repo.getRefDatabase().exactRef(refName);
    if (ref != null && ref.getObjectId() != null) {
        RevObject obj = rw.parseAny(ref.getObjectId());
        if (obj instanceof RevCommit) {
            return (RevCommit) obj;
        }
        return commit(repo, rw, tmpIns, ins, refName, obj, merge);
    }
    ResolveMerger m = (ResolveMerger) mergeStrategy.newMerger(repo, true);
    DirCache dc = DirCache.newInCore();
    m.setDirCache(dc);
    m.setObjectInserter(tmpIns == null ? new NonFlushingWrapper(ins) : tmpIns);
    boolean couldMerge;
    try {
        couldMerge = m.merge(merge.getParents());
    } catch (IOException e) {
        // It is not safe to continue further down in this method as throwing
        // an exception most likely means that the merge tree was not created
        // and m.getMergeResults() is empty. This would mean that all paths are
        // unmerged and Gerrit UI would show all paths in the patch list.
        log.warn("Error attempting automerge " + refName, e);
        return null;
    }
    ObjectId treeId;
    if (couldMerge) {
        treeId = m.getResultTreeId();
    } else {
        RevCommit ours = merge.getParent(0);
        RevCommit theirs = merge.getParent(1);
        rw.parseBody(ours);
        rw.parseBody(theirs);
        String oursMsg = ours.getShortMessage();
        String theirsMsg = theirs.getShortMessage();
        String oursName = String.format("HEAD   (%s %s)", ours.abbreviate(6).name(), oursMsg.substring(0, Math.min(oursMsg.length(), 60)));
        String theirsName = String.format("BRANCH (%s %s)", theirs.abbreviate(6).name(), theirsMsg.substring(0, Math.min(theirsMsg.length(), 60)));
        MergeFormatter fmt = new MergeFormatter();
        Map<String, MergeResult<? extends Sequence>> r = m.getMergeResults();
        Map<String, ObjectId> resolved = new HashMap<>();
        for (Map.Entry<String, MergeResult<? extends Sequence>> entry : r.entrySet()) {
            MergeResult<? extends Sequence> p = entry.getValue();
            try (TemporaryBuffer buf = new TemporaryBuffer.LocalFile(null, 10 * 1024 * 1024)) {
                fmt.formatMerge(buf, p, "BASE", oursName, theirsName, UTF_8.name());
                buf.close();
                try (InputStream in = buf.openInputStream()) {
                    resolved.put(entry.getKey(), ins.insert(Constants.OBJ_BLOB, buf.length(), in));
                }
            }
        }
        DirCacheBuilder builder = dc.builder();
        int cnt = dc.getEntryCount();
        for (int i = 0; i < cnt; ) {
            DirCacheEntry entry = dc.getEntry(i);
            if (entry.getStage() == 0) {
                builder.add(entry);
                i++;
                continue;
            }
            int next = dc.nextEntry(i);
            String path = entry.getPathString();
            DirCacheEntry res = new DirCacheEntry(path);
            if (resolved.containsKey(path)) {
                // For a file with content merge conflict that we produced a result
                // above on, collapse the file down to a single stage 0 with just
                // the blob content, and a randomly selected mode (the lowest stage,
                // which should be the merge base, or ours).
                res.setFileMode(entry.getFileMode());
                res.setObjectId(resolved.get(path));
            } else if (next == i + 1) {
                // If there is exactly one stage present, shouldn't be a conflict...
                res.setFileMode(entry.getFileMode());
                res.setObjectId(entry.getObjectId());
            } else if (next == i + 2) {
                // Two stages suggests a delete/modify conflict. Pick the higher
                // stage as the automatic result.
                entry = dc.getEntry(i + 1);
                res.setFileMode(entry.getFileMode());
                res.setObjectId(entry.getObjectId());
            } else {
                // 3 stage conflict, no resolve above
                // Punt on the 3-stage conflict and show the base, for now.
                res.setFileMode(entry.getFileMode());
                res.setObjectId(entry.getObjectId());
            }
            builder.add(res);
            i = next;
        }
        builder.finish();
        treeId = dc.writeTree(ins);
    }
    return commit(repo, rw, tmpIns, ins, refName, treeId, merge);
}
Also used : DirCacheBuilder(org.eclipse.jgit.dircache.DirCacheBuilder) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) HashMap(java.util.HashMap) MergeResult(org.eclipse.jgit.merge.MergeResult) RevCommit(org.eclipse.jgit.revwalk.RevCommit) RevObject(org.eclipse.jgit.revwalk.RevObject) ObjectId(org.eclipse.jgit.lib.ObjectId) InputStream(java.io.InputStream) InMemoryInserter(com.google.gerrit.server.git.InMemoryInserter) IOException(java.io.IOException) Sequence(org.eclipse.jgit.diff.Sequence) ResolveMerger(org.eclipse.jgit.merge.ResolveMerger) DirCache(org.eclipse.jgit.dircache.DirCache) Ref(org.eclipse.jgit.lib.Ref) TemporaryBuffer(org.eclipse.jgit.util.TemporaryBuffer) HashMap(java.util.HashMap) Map(java.util.Map) MergeFormatter(org.eclipse.jgit.merge.MergeFormatter)

Example 7 with DirCacheEntry

use of org.eclipse.jgit.dircache.DirCacheEntry in project gitiles by GerritCodeReview.

the class PathServletTest method symlinkText.

@Test
public void symlinkText() throws Exception {
    final RevBlob link = repo.blob("foo");
    repo.branch("master").commit().edit(new PathEdit("baz") {

        @Override
        public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.SYMLINK);
            ent.setObjectId(link);
        }
    }).create();
    String text = buildBlob("/repo/+/master/baz", "120000");
    assertThat(text).isEqualTo("foo");
}
Also used : DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) RevBlob(org.eclipse.jgit.revwalk.RevBlob) PathEdit(org.eclipse.jgit.dircache.DirCacheEditor.PathEdit) Test(org.junit.Test)

Example 8 with DirCacheEntry

use of org.eclipse.jgit.dircache.DirCacheEntry in project gitiles by GerritCodeReview.

the class PathServletTest method symlinkHtml.

@Test
public void symlinkHtml() throws Exception {
    final RevBlob link = repo.blob("foo");
    repo.branch("master").commit().add("foo", "contents").edit(new PathEdit("bar") {

        @Override
        public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.SYMLINK);
            ent.setObjectId(link);
        }
    }).create();
    Map<String, ?> data = buildData("/repo/+/master/bar");
    assertThat(data).containsEntry("type", "SYMLINK");
    assertThat(getBlobData(data)).containsEntry("target", "foo");
}
Also used : DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) RevBlob(org.eclipse.jgit.revwalk.RevBlob) PathEdit(org.eclipse.jgit.dircache.DirCacheEditor.PathEdit) Test(org.junit.Test)

Example 9 with DirCacheEntry

use of org.eclipse.jgit.dircache.DirCacheEntry in project gitblit by gitblit.

the class RefLogUtils method createIndex.

/**
	 * Creates an in-memory index of the reflog entry.
	 *
	 * @param repo
	 * @param headId
	 * @param commands
	 * @return an in-memory index
	 * @throws IOException
	 */
private static DirCache createIndex(Repository repo, ObjectId headId, Collection<ReceiveCommand> commands) throws IOException {
    DirCache inCoreIndex = DirCache.newInCore();
    DirCacheBuilder dcBuilder = inCoreIndex.builder();
    ObjectInserter inserter = repo.newObjectInserter();
    long now = System.currentTimeMillis();
    Set<String> ignorePaths = new TreeSet<String>();
    try {
        // add receive commands to the temporary index
        for (ReceiveCommand command : commands) {
            // use the ref names as the path names
            String path = command.getRefName();
            ignorePaths.add(path);
            StringBuilder change = new StringBuilder();
            change.append(command.getType().name()).append(' ');
            switch(command.getType()) {
                case CREATE:
                    change.append(ObjectId.zeroId().getName());
                    change.append(' ');
                    change.append(command.getNewId().getName());
                    break;
                case UPDATE:
                case UPDATE_NONFASTFORWARD:
                    change.append(command.getOldId().getName());
                    change.append(' ');
                    change.append(command.getNewId().getName());
                    break;
                case DELETE:
                    change = null;
                    break;
            }
            if (change == null) {
                // ref deleted
                continue;
            }
            String content = change.toString();
            // create an index entry for this attachment
            final DirCacheEntry dcEntry = new DirCacheEntry(path);
            dcEntry.setLength(content.length());
            dcEntry.setLastModified(now);
            dcEntry.setFileMode(FileMode.REGULAR_FILE);
            // insert object
            dcEntry.setObjectId(inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, content.getBytes("UTF-8")));
            // add to temporary in-core index
            dcBuilder.add(dcEntry);
        }
        // Traverse HEAD to add all other paths
        TreeWalk treeWalk = new TreeWalk(repo);
        int hIdx = -1;
        if (headId != null)
            hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId));
        treeWalk.setRecursive(true);
        while (treeWalk.next()) {
            String path = treeWalk.getPathString();
            CanonicalTreeParser hTree = null;
            if (hIdx != -1)
                hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
            if (!ignorePaths.contains(path)) {
                // add entries from HEAD for all other paths
                if (hTree != null) {
                    // create a new DirCacheEntry with data retrieved from
                    // HEAD
                    final DirCacheEntry dcEntry = new DirCacheEntry(path);
                    dcEntry.setObjectId(hTree.getEntryObjectId());
                    dcEntry.setFileMode(hTree.getEntryFileMode());
                    // add to temporary in-core index
                    dcBuilder.add(dcEntry);
                }
            }
        }
        // release the treewalk
        treeWalk.close();
        // finish temporary in-core index used for this commit
        dcBuilder.finish();
    } finally {
        inserter.close();
    }
    return inCoreIndex;
}
Also used : ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) DirCacheBuilder(org.eclipse.jgit.dircache.DirCacheBuilder) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) RevWalk(org.eclipse.jgit.revwalk.RevWalk) CanonicalTreeParser(org.eclipse.jgit.treewalk.CanonicalTreeParser) DirCache(org.eclipse.jgit.dircache.DirCache) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) TreeSet(java.util.TreeSet) TreeWalk(org.eclipse.jgit.treewalk.TreeWalk)

Example 10 with DirCacheEntry

use of org.eclipse.jgit.dircache.DirCacheEntry in project gitblit by gitblit.

the class BranchTicketService method writeTicketsFile.

/**
	 * Writes a file to the tickets branch.
	 *
	 * @param db
	 * @param file
	 * @param content
	 * @param createdBy
	 * @param msg
	 */
private void writeTicketsFile(Repository db, String file, String content, String createdBy, String msg) {
    if (getTicketsBranch(db) == null) {
        createTicketsBranch(db);
    }
    DirCache newIndex = DirCache.newInCore();
    DirCacheBuilder builder = newIndex.builder();
    ObjectInserter inserter = db.newObjectInserter();
    try {
        // create an index entry for the revised index
        final DirCacheEntry idIndexEntry = new DirCacheEntry(file);
        idIndexEntry.setLength(content.length());
        idIndexEntry.setLastModified(System.currentTimeMillis());
        idIndexEntry.setFileMode(FileMode.REGULAR_FILE);
        // insert new ticket index
        idIndexEntry.setObjectId(inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, content.getBytes(Constants.ENCODING)));
        // add to temporary in-core index
        builder.add(idIndexEntry);
        Set<String> ignorePaths = new HashSet<String>();
        ignorePaths.add(file);
        for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) {
            builder.add(entry);
        }
        // finish temporary in-core index used for this commit
        builder.finish();
        // commit the change
        commitIndex(db, newIndex, createdBy, msg);
    } catch (ConcurrentRefUpdateException e) {
        log.error("", e);
    } catch (IOException e) {
        log.error("", e);
    } finally {
        inserter.close();
    }
}
Also used : DirCache(org.eclipse.jgit.dircache.DirCache) DirCacheBuilder(org.eclipse.jgit.dircache.DirCacheBuilder) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) IOException(java.io.IOException) ConcurrentRefUpdateException(org.eclipse.jgit.api.errors.ConcurrentRefUpdateException) HashSet(java.util.HashSet)

Aggregations

DirCacheEntry (org.eclipse.jgit.dircache.DirCacheEntry)13 DirCache (org.eclipse.jgit.dircache.DirCache)6 DirCacheBuilder (org.eclipse.jgit.dircache.DirCacheBuilder)6 ObjectId (org.eclipse.jgit.lib.ObjectId)6 PathEdit (org.eclipse.jgit.dircache.DirCacheEditor.PathEdit)5 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)5 IOException (java.io.IOException)4 RevCommit (org.eclipse.jgit.revwalk.RevCommit)4 CanonicalTreeParser (org.eclipse.jgit.treewalk.CanonicalTreeParser)3 Test (org.junit.Test)3 TreeSet (java.util.TreeSet)2 DeletePath (org.eclipse.jgit.dircache.DirCacheEditor.DeletePath)2 AnyObjectId (org.eclipse.jgit.lib.AnyObjectId)2 Ref (org.eclipse.jgit.lib.Ref)2 Repository (org.eclipse.jgit.lib.Repository)2 RevBlob (org.eclipse.jgit.revwalk.RevBlob)2 RevWalk (org.eclipse.jgit.revwalk.RevWalk)2 TreeWalk (org.eclipse.jgit.treewalk.TreeWalk)2 RefModel (com.gitblit.models.RefModel)1 Attachment (com.gitblit.models.TicketModel.Attachment)1