Map ported comments to patchset-level comments on file deletion

Comments on files which are deleted in the target patchset should not
be simply dropped when we try to port them. Instead, we want to show
them in the next best location.

Before we had patchset-level comments, we intended to use the magic
/COMMIT_MSG file as fallback. With patchset-level comments, those seem
better suited. The only downside is that patchset-level comments don't
appear in the "Files" section (yet).

This change adapts GitPositionTransformer to explicitly handle positions
without file paths and to also support file deletions. The actual
mapping of a no-file position to a patchset-level comment is covered
by the previous change Idd4fbe961.

In theory, this change also fixes the handling of file deletions in the
context of edits due to rebase. It won't have any user-visible impact,
though, as there's no code path relating to edits due to rebase which
will have a different end result now. The reason for this is that we
filter the "mappings" early on with respect to touched files (outside of
GitPositionTransformer and EditTransformer) and hence only
non-deletion/non-addition mappings are given to GitPositionTransformer.

This change also adds a way to express a file addition as mapping. For
GitPositionTransformer, file additions are meaningless and simply
ignored. The API still allows to create such mappings as code paths
using GitPositionTransformer shouldn't need to care about such details
of the transformation algorithm. It's also simpler code wise to
translate all potential diff outcomes to a mapping instead of having to
add additional code for filtering of file additions outside of
GitPositionTransformer.

Change-Id: If8ed1e511a91651f228fc9515311bfd3c4df048d
This commit is contained in:
Alice Kober-Sotzek
2020-08-18 12:06:47 +02:00
parent 5a5dbfdf3b
commit bf14dcbb04
3 changed files with 109 additions and 39 deletions

View File

@@ -16,7 +16,6 @@ package com.google.gerrit.server.patch;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.server.patch.GitPositionTransformer.FileMapping;
import com.google.gerrit.server.patch.GitPositionTransformer.Mapping;
@@ -29,24 +28,36 @@ public class DiffMappings {
private DiffMappings() {}
public static Mapping toMapping(PatchListEntry patchListEntry) {
// This is just a direct translation of the former logic in EditTransformer. It doesn't
// work for file deletions, though. As file deletions aren't relevant for 'edits due to rebase'
// situations, we didn't notice this in the past.
// TODO(aliceks): Fix for file deletions in another change.
FileMapping fileMapping =
FileMapping.create(getOldFilePath(patchListEntry), patchListEntry.getNewName());
ImmutableSet<RangeMapping> rangeMappings =
patchListEntry.getEdits().stream()
.map(
edit ->
RangeMapping.create(
Range.create(edit.getBeginA(), edit.getEndA()),
Range.create(edit.getBeginB(), edit.getEndB())))
.collect(toImmutableSet());
FileMapping fileMapping = toFileMapping(patchListEntry);
ImmutableSet<RangeMapping> rangeMappings = toRangeMappings(patchListEntry);
return Mapping.create(fileMapping, rangeMappings);
}
private static String getOldFilePath(PatchListEntry patchListEntry) {
return MoreObjects.firstNonNull(patchListEntry.getOldName(), patchListEntry.getNewName());
private static FileMapping toFileMapping(PatchListEntry patchListEntry) {
switch (patchListEntry.getChangeType()) {
case ADDED:
return FileMapping.forAddedFile(patchListEntry.getNewName());
case MODIFIED:
case REWRITE:
return FileMapping.forModifiedFile(patchListEntry.getNewName());
case DELETED:
// Name of deleted file is mentioned as newName.
return FileMapping.forDeletedFile(patchListEntry.getNewName());
case RENAMED:
case COPIED:
return FileMapping.forRenamedFile(patchListEntry.getOldName(), patchListEntry.getNewName());
default:
throw new IllegalStateException("Unmapped diff type: " + patchListEntry.getChangeType());
}
}
private static ImmutableSet<RangeMapping> toRangeMappings(PatchListEntry patchListEntry) {
return patchListEntry.getEdits().stream()
.map(
edit ->
RangeMapping.create(
Range.create(edit.getBeginA(), edit.getEndA()),
Range.create(edit.getBeginB(), edit.getEndB())))
.collect(toImmutableSet());
}
}