ChangeBundle: Handle leading/trailing whitespace in topic/desc PatchSet descriptions should use the same logic as Change topics to ignore whitespace that JGit won't accurately parse out of a NoteDb footer. While writing this, I found that topics should actually be trimming leading as well as trailing whitespace. Use a single trimming implementation for both of these. Change-Id: I564fe674d9b5970717cb3e923b0aa28522c6347a
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeBundle.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeBundle.java index e140f2d..1fe0e64 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeBundle.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeBundle.java
@@ -438,7 +438,7 @@ excludeCurrentPatchSetId = !bundleA.validPatchSetPredicate().apply(a.currentPatchSetId()); excludeSubject = bSubj.startsWith(aSubj) || excludeCurrentPatchSetId; excludeOrigSubj = true; - String aTopic = trimLeadingOrNull(a.getTopic()); + String aTopic = trimOrNull(a.getTopic()); excludeTopic = Objects.equals(aTopic, b.getTopic()) || "".equals(aTopic) && b.getTopic() == null; aUpdated = bundleA.getLatestTimestamp(); @@ -450,7 +450,7 @@ excludeCurrentPatchSetId = !bundleB.validPatchSetPredicate().apply(b.currentPatchSetId()); excludeSubject = aSubj.startsWith(bSubj) || excludeCurrentPatchSetId; excludeOrigSubj = true; - String bTopic = trimLeadingOrNull(b.getTopic()); + String bTopic = trimOrNull(b.getTopic()); excludeTopic = Objects.equals(bTopic, a.getTopic()) || a.getTopic() == null && "".equals(bTopic); bUpdated = bundleB.getLatestTimestamp(); @@ -486,8 +486,8 @@ } } - private static String trimLeadingOrNull(String s) { - return s != null ? CharMatcher.whitespace().trimLeadingFrom(s) : null; + private static String trimOrNull(String s) { + return s != null ? CharMatcher.whitespace().trimFrom(s) : null; } private static String cleanReviewDbSubject(String s) { @@ -653,7 +653,20 @@ PatchSet b = bs.get(id); String desc = describe(id); String pushCertField = "pushCertificate"; - diffColumnsExcluding(diffs, PatchSet.class, desc, bundleA, a, bundleB, b, pushCertField); + + boolean excludeDesc = false; + if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) { + excludeDesc = Objects.equals(trimOrNull(a.getDescription()), b.getDescription()); + } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) { + excludeDesc = Objects.equals(a.getDescription(), trimOrNull(b.getDescription())); + } + + List<String> exclude = Lists.newArrayList(pushCertField); + if (excludeDesc) { + exclude.add("description"); + } + + diffColumnsExcluding(diffs, PatchSet.class, desc, bundleA, a, bundleB, b, exclude); diffValues(diffs, desc, trimPushCert(a), trimPushCert(b), pushCertField); } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeBundleTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeBundleTest.java index f095347..151a053 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeBundleTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeBundleTest.java
@@ -355,9 +355,9 @@ } @Test - public void diffChangesIgnoresLeadingWhitespaceInReviewDbTopics() throws Exception { + public void diffChangesIgnoresLeadingAndTrailingWhitespaceInReviewDbTopics() throws Exception { Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100)); - c1.setTopic(" abc"); + c1.setTopic(" abc "); Change c2 = clone(c1); c2.setTopic("abc"); @@ -368,7 +368,7 @@ ChangeBundle b2 = new ChangeBundle( c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB); - assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ":" + " { abc} != {abc}"); + assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ":" + " { abc } != {abc}"); // Leading whitespace in ReviewDb topic is ignored. b1 = @@ -380,7 +380,7 @@ assertNoDiffs(b1, b2); assertNoDiffs(b2, b1); - // Must match except for the leading whitespace. + // Must match except for the leading/trailing whitespace. Change c3 = clone(c1); c3.setTopic("cba"); b1 = @@ -389,7 +389,7 @@ b2 = new ChangeBundle( c3, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB); - assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ":" + " { abc} != {cba}"); + assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ":" + " { abc } != {cba}"); } @Test @@ -1245,6 +1245,52 @@ } @Test + public void diffPatchSetsIgnoresLeadingAndTrailingWhitespaceInReviewDbDescriptions() + throws Exception { + Change c = TestChanges.newChange(project, accountId); + + PatchSet ps1 = new PatchSet(new PatchSet.Id(c.getId(), 1)); + ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); + ps1.setUploader(accountId); + ps1.setCreatedOn(TimeUtil.nowTs()); + ps1.setDescription(" abc "); + PatchSet ps2 = clone(ps1); + ps2.setDescription("abc"); + + // Both ReviewDb, exact match required. + ChangeBundle b1 = + new ChangeBundle( + c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB); + ChangeBundle b2 = + new ChangeBundle( + c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB); + assertDiffs( + b1, b2, "description differs for PatchSet.Id " + ps1.getId() + ":" + " { abc } != {abc}"); + + // Whitespace in ReviewDb description is ignored. + b1 = + new ChangeBundle( + c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB); + b2 = + new ChangeBundle( + c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), NOTE_DB); + assertNoDiffs(b1, b2); + assertNoDiffs(b2, b1); + + // Must match except for the leading/trailing whitespace. + PatchSet ps3 = clone(ps1); + ps3.setDescription("cba"); + b1 = + new ChangeBundle( + c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB); + b2 = + new ChangeBundle( + c, messages(), patchSets(ps3), approvals(), comments(), reviewers(), NOTE_DB); + assertDiffs( + b1, b2, "description differs for PatchSet.Id " + ps1.getId() + ":" + " { abc } != {cba}"); + } + + @Test public void diffPatchSetApprovalKeySets() throws Exception { Change c = TestChanges.newChange(project, accountId); int id = c.getId().get();