Search in sources :

Example 1 with FileDiffOutput

use of com.google.gerrit.server.patch.filediff.FileDiffOutput in project gerrit by GerritCodeReview.

the class DiffOperationsImpl method getModifiedFilesForKeys.

/**
 * Lookup the file diffs for the input {@code keys}. For results where the cache reports negative
 * results, e.g. due to timeouts in the cache loader, this method requests the diff again using
 * the fallback algorithm {@link DiffAlgorithm#HISTOGRAM_NO_FALLBACK}.
 */
private ImmutableMap<String, FileDiffOutput> getModifiedFilesForKeys(List<FileDiffCacheKey> keys, DiffOptions diffOptions) throws DiffNotAvailableException {
    ImmutableMap<FileDiffCacheKey, FileDiffOutput> fileDiffs = fileDiffCache.getAll(keys);
    List<FileDiffCacheKey> fallbackKeys = new ArrayList<>();
    ImmutableList.Builder<FileDiffOutput> result = ImmutableList.builder();
    // Use the fallback diff algorithm for negative results
    for (FileDiffCacheKey key : fileDiffs.keySet()) {
        FileDiffOutput diff = fileDiffs.get(key);
        if (diff.isNegative()) {
            FileDiffCacheKey fallbackKey = createFileDiffCacheKey(key.project(), key.oldCommit(), key.newCommit(), key.newFilePath(), // Use the fallback diff algorithm
            DiffAlgorithm.HISTOGRAM_NO_FALLBACK, /* useTimeout= */
            false, key.whitespace());
            fallbackKeys.add(fallbackKey);
        } else {
            result.add(diff);
        }
    }
    result.addAll(fileDiffCache.getAll(fallbackKeys).values());
    return mapByFilePath(result.build(), diffOptions);
}
Also used : FileDiffCacheKey(com.google.gerrit.server.patch.filediff.FileDiffCacheKey) ImmutableList(com.google.common.collect.ImmutableList) ArrayList(java.util.ArrayList) FileDiffOutput(com.google.gerrit.server.patch.filediff.FileDiffOutput)

Example 2 with FileDiffOutput

use of com.google.gerrit.server.patch.filediff.FileDiffOutput in project gerrit by GerritCodeReview.

the class ChangeEmail method getUnifiedDiff.

/**
 * Show patch set as unified difference.
 */
public String getUnifiedDiff() {
    Map<String, FileDiffOutput> modifiedFiles;
    try {
        modifiedFiles = listModifiedFiles();
        if (modifiedFiles.isEmpty()) {
            // Currently these always have a null oldId in the PatchList.
            return "[Octopus merge; cannot be formatted as a diff.]\n";
        }
    } catch (DiffNotAvailableException e) {
        logger.atSevere().withCause(e).log("Cannot format patch");
        return "";
    }
    int maxSize = args.settings.maximumDiffSize;
    TemporaryBuffer.Heap buf = new TemporaryBuffer.Heap(Math.min(HEAP_EST_SIZE, maxSize), maxSize);
    try (DiffFormatter fmt = new DiffFormatter(buf)) {
        try (Repository git = args.server.openRepository(change.getProject())) {
            try {
                ObjectId oldId = modifiedFiles.values().iterator().next().oldCommitId();
                ObjectId newId = modifiedFiles.values().iterator().next().newCommitId();
                if (oldId.equals(ObjectId.zeroId())) {
                    // DiffOperations returns ObjectId.zeroId if newCommit is a root commit, i.e. has no
                    // parents.
                    oldId = null;
                }
                fmt.setRepository(git);
                fmt.setDetectRenames(true);
                fmt.format(oldId, newId);
                return RawParseUtils.decode(buf.toByteArray());
            } catch (IOException e) {
                if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) {
                    return "";
                }
                logger.atSevere().withCause(e).log("Cannot format patch");
                return "";
            }
        } catch (IOException e) {
            logger.atSevere().withCause(e).log("Cannot open repository to format patch");
            return "";
        }
    }
}
Also used : Repository(org.eclipse.jgit.lib.Repository) DiffNotAvailableException(com.google.gerrit.server.patch.DiffNotAvailableException) TemporaryBuffer(org.eclipse.jgit.util.TemporaryBuffer) ObjectId(org.eclipse.jgit.lib.ObjectId) IOException(java.io.IOException) DiffFormatter(org.eclipse.jgit.diff.DiffFormatter) FileDiffOutput(com.google.gerrit.server.patch.filediff.FileDiffOutput)

Example 3 with FileDiffOutput

use of com.google.gerrit.server.patch.filediff.FileDiffOutput in project gerrit by GerritCodeReview.

the class FileInfoJsonImpl method asFileInfo.

private Map<String, FileInfo> asFileInfo(Map<String, FileDiffOutput> fileDiffs) {
    Map<String, FileInfo> result = new HashMap<>();
    for (String path : fileDiffs.keySet()) {
        FileDiffOutput fileDiff = fileDiffs.get(path);
        FileInfo fileInfo = new FileInfo();
        fileInfo.status = fileDiff.changeType() != Patch.ChangeType.MODIFIED ? fileDiff.changeType().getCode() : null;
        fileInfo.oldPath = FilePathAdapter.getOldPath(fileDiff.oldPath(), fileDiff.changeType());
        fileInfo.sizeDelta = fileDiff.sizeDelta();
        fileInfo.size = fileDiff.size();
        if (fileDiff.patchType().get() == Patch.PatchType.BINARY) {
            fileInfo.binary = true;
        } else {
            fileInfo.linesInserted = fileDiff.insertions() > 0 ? fileDiff.insertions() : null;
            fileInfo.linesDeleted = fileDiff.deletions() > 0 ? fileDiff.deletions() : null;
        }
        result.put(path, fileInfo);
    }
    return result;
}
Also used : FileInfo(com.google.gerrit.extensions.common.FileInfo) HashMap(java.util.HashMap) FileDiffOutput(com.google.gerrit.server.patch.filediff.FileDiffOutput)

Example 4 with FileDiffOutput

use of com.google.gerrit.server.patch.filediff.FileDiffOutput in project gerrit by GerritCodeReview.

the class FileEditsPredicate method match.

@Override
public boolean match(ChangeData cd) {
    try {
        Map<String, FileDiffOutput> modifiedFiles = diffOperations.listModifiedFilesAgainstParent(cd.project(), cd.currentPatchSet().commitId(), /* parentNum= */
        0, DiffOptions.DEFAULTS);
        FileDiffOutput firstDiff = Iterables.getFirst(modifiedFiles.values(), /* defaultValue= */
        null);
        if (firstDiff == null) {
            // engine.fail();
            return false;
        }
        Pattern filePattern = null;
        Pattern editPattern = null;
        if (fileEditsArgs.filePattern().startsWith("^")) {
            // We validated the pattern before creating this predicate. No need to revalidate.
            String pattern = fileEditsArgs.filePattern();
            filePattern = Pattern.compile(pattern);
        }
        if (fileEditsArgs.editPattern().startsWith("^")) {
            // We validated the pattern before creating this predicate. No need to revalidate.
            String pattern = fileEditsArgs.editPattern();
            editPattern = Pattern.compile(pattern);
        }
        try (Repository repo = repoManager.openRepository(cd.project());
            ObjectReader reader = repo.newObjectReader();
            RevWalk rw = new RevWalk(reader)) {
            RevTree aTree = firstDiff.oldCommitId().equals(ObjectId.zeroId()) ? null : rw.parseTree(firstDiff.oldCommitId());
            RevTree bTree = rw.parseCommit(firstDiff.newCommitId()).getTree();
            for (FileDiffOutput entry : modifiedFiles.values()) {
                String newName = FilePathAdapter.getNewPath(entry.oldPath(), entry.newPath(), entry.changeType());
                String oldName = FilePathAdapter.getOldPath(entry.oldPath(), entry.changeType());
                if (Patch.isMagic(newName)) {
                    continue;
                }
                if (match(newName, fileEditsArgs.filePattern(), filePattern) || (oldName != null && match(oldName, fileEditsArgs.filePattern(), filePattern))) {
                    List<Edit> edits = entry.edits().stream().map(TaggedEdit::jgitEdit).collect(Collectors.toList());
                    if (edits.isEmpty()) {
                        continue;
                    }
                    Text tA;
                    if (oldName != null) {
                        tA = load(aTree, oldName, reader);
                    } else {
                        tA = load(aTree, newName, reader);
                    }
                    Text tB = load(bTree, newName, reader);
                    for (Edit edit : edits) {
                        if (tA != Text.EMPTY) {
                            String aDiff = tA.getString(edit.getBeginA(), edit.getEndA(), true);
                            if (match(aDiff, fileEditsArgs.editPattern(), editPattern)) {
                                return true;
                            }
                        }
                        if (tB != Text.EMPTY) {
                            String bDiff = tB.getString(edit.getBeginB(), edit.getEndB(), true);
                            if (match(bDiff, fileEditsArgs.editPattern(), editPattern)) {
                                return true;
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            logger.atSevere().withCause(e).log("Error while evaluating commit edits.");
            return false;
        }
    } catch (DiffNotAvailableException e) {
        logger.atSevere().withCause(e).log("Diff error while evaluating commit edits.");
        return false;
    }
    return false;
}
Also used : Pattern(java.util.regex.Pattern) Edit(org.eclipse.jgit.diff.Edit) TaggedEdit(com.google.gerrit.server.patch.filediff.TaggedEdit) Text(com.google.gerrit.server.patch.Text) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) FileDiffOutput(com.google.gerrit.server.patch.filediff.FileDiffOutput) Repository(org.eclipse.jgit.lib.Repository) DiffNotAvailableException(com.google.gerrit.server.patch.DiffNotAvailableException) ObjectReader(org.eclipse.jgit.lib.ObjectReader) RevTree(org.eclipse.jgit.revwalk.RevTree)

Example 5 with FileDiffOutput

use of com.google.gerrit.server.patch.filediff.FileDiffOutput in project gerrit by GerritCodeReview.

the class DiffOperationsTest method diffModifiedFileAgainstParent.

@Test
public void diffModifiedFileAgainstParent() throws Exception {
    ImmutableList<FileEntity> oldFiles = ImmutableList.of(new FileEntity(fileName1, fileContent1), new FileEntity(fileName2, fileContent2));
    ObjectId oldCommitId = createCommit(repo, null, oldFiles);
    ImmutableList<FileEntity> newFiles = ImmutableList.of(new FileEntity(fileName1, fileContent1), new FileEntity(fileName2, fileContent2 + "\nnew line here"));
    ObjectId newCommitId = createCommit(repo, oldCommitId, newFiles);
    FileDiffOutput diffOutput = diffOperations.getModifiedFileAgainstParent(testProjectName, newCommitId, /* parentNum=*/
    0, fileName2, /* whitespace=*/
    null);
    assertThat(diffOutput.oldCommitId()).isEqualTo(oldCommitId);
    assertThat(diffOutput.newCommitId()).isEqualTo(newCommitId);
    assertThat(diffOutput.comparisonType().isAgainstParent()).isTrue();
    assertThat(diffOutput.edits()).hasSize(1);
}
Also used : ObjectId(org.eclipse.jgit.lib.ObjectId) FileDiffOutput(com.google.gerrit.server.patch.filediff.FileDiffOutput) Test(org.junit.Test)

Aggregations

FileDiffOutput (com.google.gerrit.server.patch.filediff.FileDiffOutput)20 IOException (java.io.IOException)10 DiffNotAvailableException (com.google.gerrit.server.patch.DiffNotAvailableException)6 Repository (org.eclipse.jgit.lib.Repository)6 ArrayList (java.util.ArrayList)5 ObjectId (org.eclipse.jgit.lib.ObjectId)5 RevWalk (org.eclipse.jgit.revwalk.RevWalk)5 Patch (com.google.gerrit.entities.Patch)4 StorageException (com.google.gerrit.exceptions.StorageException)4 Test (org.junit.Test)4 Project (com.google.gerrit.entities.Project)3 Inject (com.google.inject.Inject)3 Term (com.googlecode.prolog_cafe.lang.Term)3 List (java.util.List)3 Map (java.util.Map)3 Optional (java.util.Optional)3 Config (org.eclipse.jgit.lib.Config)3 ImmutableList (com.google.common.collect.ImmutableList)2 FluentLogger (com.google.common.flogger.FluentLogger)2 Nullable (com.google.gerrit.common.Nullable)2