Fix bug excluding some renamed files from patch set diff
Files which were renamed between two patch sets but contained only hunks due to rebase were erroneously excluded from the set of modified files. The tricky part is to identify which renames truly happen between patch sets. To be able to distinguish different types of renames, we use a flag to mark all renames which are introduced when transforming the diff hunks between the parents to ones between the patch sets. This flag is only relevant when deciding which files should be excluded from the diff. The current fix might not be the most elegant solution and might not be perfect, but it seems to result in the correct behavior. Change-Id: I7dfd81961803110fd65932e0bcba7f79dd462079
This commit is contained in:
parent
704ba94fae
commit
a29041ce24
@ -249,6 +249,61 @@ public class RevisionDiffIT extends AbstractDaemonTest {
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG, FILE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renamedUnrelatedFileIsIgnored_ForPatchSetDiffWithRebase_WhenModifiedDuringRebase()
|
||||
throws Exception {
|
||||
String renamedFilePath = "renamed_some_file.txt";
|
||||
ObjectId commit2 =
|
||||
addCommit(commit1, FILE_NAME, FILE_CONTENT.replace("Line 5\n", "Line five\n"));
|
||||
ObjectId commit3 = addCommitRenamingFile(commit2, FILE_NAME, renamedFilePath);
|
||||
|
||||
rebaseChangeOn(changeId, commit3);
|
||||
|
||||
Map<String, FileInfo> changedFiles =
|
||||
gApi.changes().id(changeId).current().files(initialPatchSetId);
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileRenamedDuringRebaseSameAsInPatchSetIsIgnored() throws Exception {
|
||||
String renamedFileName = "renamed_file.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, renamedFileName);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
|
||||
|
||||
// Revert the renaming to be able to rebase.
|
||||
gApi.changes().id(changeId).edit().renameFile(renamedFileName, FILE_NAME);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
ObjectId commit2 = addCommitRenamingFile(commit1, FILE_NAME, renamedFileName);
|
||||
rebaseChangeOn(changeId, commit2);
|
||||
|
||||
Map<String, FileInfo> changedFiles =
|
||||
gApi.changes().id(changeId).current().files(previousPatchSetId);
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileWithRebaseHunksRenamedDuringRebaseSameAsInPatchSetIsIgnored() throws Exception {
|
||||
String renamedFileName = "renamed_file.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, renamedFileName);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
|
||||
|
||||
// Revert the renaming to be able to rebase.
|
||||
gApi.changes().id(changeId).edit().renameFile(renamedFileName, FILE_NAME);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
ObjectId commit2 =
|
||||
addCommit(commit1, FILE_NAME, FILE_CONTENT.replace("Line 10\n", "Line ten\n"));
|
||||
ObjectId commit3 = addCommitRenamingFile(commit2, FILE_NAME, renamedFileName);
|
||||
rebaseChangeOn(changeId, commit3);
|
||||
|
||||
Map<String, FileInfo> changedFiles =
|
||||
gApi.changes().id(changeId).current().files(previousPatchSetId);
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filesNotTouchedByPatchSetsAndContainingOnlyRebaseHunksAreIgnored() throws Exception {
|
||||
String newFileContent = FILE_CONTENT.replace("Line 10\n", "Line ten\n");
|
||||
@ -912,6 +967,78 @@ public class RevisionDiffIT extends AbstractDaemonTest {
|
||||
assertThat(changedFiles.get(renamedFilePath)).linesDeleted().isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renamedFileWithOnlyRebaseHunksIsIdentified_WhenRenamedBetweenPatchSets()
|
||||
throws Exception {
|
||||
String newFilePath1 = "renamed_some_file.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, newFilePath1);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
|
||||
|
||||
// Revert the renaming to be able to rebase.
|
||||
gApi.changes().id(changeId).edit().renameFile(newFilePath1, FILE_NAME);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
ObjectId commit2 =
|
||||
addCommit(commit1, FILE_NAME, FILE_CONTENT.replace("Line 5\n", "Line five\n"));
|
||||
|
||||
rebaseChangeOn(changeId, commit2);
|
||||
String newFilePath2 = "renamed_some_file_to_something_else.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, newFilePath2);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
Map<String, FileInfo> changedFiles =
|
||||
gApi.changes().id(changeId).current().files(previousPatchSetId);
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG, newFilePath2);
|
||||
assertThat(changedFiles.get(newFilePath2)).linesInserted().isNull();
|
||||
assertThat(changedFiles.get(newFilePath2)).linesDeleted().isNull();
|
||||
|
||||
DiffInfo diffInfo =
|
||||
getDiffRequest(changeId, CURRENT, newFilePath2).withBase(previousPatchSetId).get();
|
||||
assertThat(diffInfo).content().element(0).commonLines().hasSize(4);
|
||||
assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 5");
|
||||
assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line five");
|
||||
assertThat(diffInfo).content().element(1).isDueToRebase();
|
||||
assertThat(diffInfo).content().element(2).commonLines().hasSize(95);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renamedFileWithOnlyRebaseHunksIsIdentified_WhenRenamedForRebaseAndForPatchSets()
|
||||
throws Exception {
|
||||
String newFilePath1 = "renamed_some_file.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, newFilePath1);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
|
||||
|
||||
// Revert the renaming to be able to rebase.
|
||||
gApi.changes().id(changeId).edit().renameFile(newFilePath1, FILE_NAME);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
ObjectId commit2 =
|
||||
addCommit(commit1, FILE_NAME, FILE_CONTENT.replace("Line 5\n", "Line five\n"));
|
||||
String newFilePath2 = "renamed_some_file_during_rebase.txt";
|
||||
ObjectId commit3 = addCommitRenamingFile(commit2, FILE_NAME, newFilePath2);
|
||||
|
||||
rebaseChangeOn(changeId, commit3);
|
||||
String newFilePath3 = "renamed_some_file_to_something_else.txt";
|
||||
gApi.changes().id(changeId).edit().renameFile(newFilePath2, newFilePath3);
|
||||
gApi.changes().id(changeId).edit().publish();
|
||||
|
||||
Map<String, FileInfo> changedFiles =
|
||||
gApi.changes().id(changeId).current().files(previousPatchSetId);
|
||||
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG, newFilePath3);
|
||||
assertThat(changedFiles.get(newFilePath3)).linesInserted().isNull();
|
||||
assertThat(changedFiles.get(newFilePath3)).linesDeleted().isNull();
|
||||
|
||||
DiffInfo diffInfo =
|
||||
getDiffRequest(changeId, CURRENT, newFilePath3).withBase(previousPatchSetId).get();
|
||||
assertThat(diffInfo).content().element(0).commonLines().hasSize(4);
|
||||
assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 5");
|
||||
assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line five");
|
||||
assertThat(diffInfo).content().element(1).isDueToRebase();
|
||||
assertThat(diffInfo).content().element(2).commonLines().hasSize(95);
|
||||
}
|
||||
|
||||
/*
|
||||
* change PS B
|
||||
* |
|
||||
|
@ -29,6 +29,7 @@ import com.google.common.collect.Multimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
@ -186,18 +187,27 @@ class EditTransformer {
|
||||
edit.getBeginA(),
|
||||
edit.getEndA(),
|
||||
edit.getBeginB(),
|
||||
edit.getEndB());
|
||||
edit.getEndB(),
|
||||
false);
|
||||
}
|
||||
|
||||
static ContextAwareEdit createForNoContentEdit(PatchListEntry patchListEntry) {
|
||||
return create(patchListEntry.getOldName(), patchListEntry.getNewName(), -1, -1, -1, -1);
|
||||
return create(
|
||||
patchListEntry.getOldName(), patchListEntry.getNewName(), -1, -1, -1, -1, false);
|
||||
}
|
||||
|
||||
static ContextAwareEdit create(
|
||||
String oldFilePath, String newFilePath, int beginA, int endA, int beginB, int endB) {
|
||||
String oldFilePath,
|
||||
String newFilePath,
|
||||
int beginA,
|
||||
int endA,
|
||||
int beginB,
|
||||
int endB,
|
||||
boolean filePathAdjusted) {
|
||||
String adjustedOldFilePath = MoreObjects.firstNonNull(oldFilePath, newFilePath);
|
||||
boolean implicitRename = !Objects.equals(oldFilePath, newFilePath) && filePathAdjusted;
|
||||
return new AutoValue_EditTransformer_ContextAwareEdit(
|
||||
adjustedOldFilePath, newFilePath, beginA, endA, beginB, endB);
|
||||
adjustedOldFilePath, newFilePath, beginA, endA, beginB, endB, implicitRename);
|
||||
}
|
||||
|
||||
public abstract String getOldFilePath();
|
||||
@ -212,6 +222,9 @@ class EditTransformer {
|
||||
|
||||
public abstract int getEndB();
|
||||
|
||||
// Used for equals(), for which this value is important.
|
||||
public abstract boolean isImplicitRename();
|
||||
|
||||
public Optional<Edit> toEdit() {
|
||||
if (getBeginA() < 0) {
|
||||
return Optional.empty();
|
||||
@ -258,7 +271,8 @@ class EditTransformer {
|
||||
edit.getBeginA() + shiftedAmount,
|
||||
edit.getEndA() + shiftedAmount,
|
||||
edit.getBeginB(),
|
||||
edit.getEndB());
|
||||
edit.getEndB(),
|
||||
!Objects.equals(edit.getOldFilePath(), adjustedFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,7 +303,8 @@ class EditTransformer {
|
||||
edit.getBeginA(),
|
||||
edit.getEndA(),
|
||||
edit.getBeginB() + shiftedAmount,
|
||||
edit.getEndB() + shiftedAmount);
|
||||
edit.getEndB() + shiftedAmount,
|
||||
!Objects.equals(edit.getNewFilePath(), adjustedFilePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import org.eclipse.jgit.lib.ObjectId;
|
||||
|
||||
@AutoValue
|
||||
public abstract class IntraLineDiffKey implements Serializable {
|
||||
public static final long serialVersionUID = 7L;
|
||||
public static final long serialVersionUID = 8L;
|
||||
|
||||
public static IntraLineDiffKey create(ObjectId aId, ObjectId bId, Whitespace whitespace) {
|
||||
return new AutoValue_IntraLineDiffKey(aId, bId, whitespace);
|
||||
|
@ -32,7 +32,7 @@ import org.eclipse.jgit.lib.AnyObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
|
||||
public class PatchListKey implements Serializable {
|
||||
public static final long serialVersionUID = 27L;
|
||||
public static final long serialVersionUID = 28L;
|
||||
|
||||
public enum Algorithm {
|
||||
PURE_TREE_DIFF,
|
||||
|
Loading…
Reference in New Issue
Block a user