Skip to content

Commit dcbdc8e

Browse files
committed
Issue #109 Fix fingerprint to use stable sorted representation
1 parent d611202 commit dcbdc8e

File tree

1 file changed

+29
-12
lines changed
  • json-java21-api-tracker/src/main/java/io/github/simbo1905/tracker

1 file changed

+29
-12
lines changed

json-java21-api-tracker/src/main/java/io/github/simbo1905/tracker/ApiTracker.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,7 @@ static String fetchUpstreamSource(String className) {
951951
}
952952

953953
/// Generates a SHA256 fingerprint of the differences (first 7 chars)
954+
/// Uses only essential, stable information: class names and change types (sorted)
954955
/// Used for deduplicating GitHub issues
955956
/// @param report the full comparison report
956957
/// @return 7-character fingerprint or "0000000" if no differences
@@ -962,30 +963,46 @@ static String generateFingerprint(JsonObject report) {
962963
return "0000000";
963964
}
964965

965-
// Extract just the differences array for fingerprinting
966+
// Build a stable, sorted representation of just the essential diff info
966967
final var differences = (JsonArray) report.members().get("differences");
967-
final var diffsOnly = differences.values().stream()
968-
.filter(v -> {
969-
final var obj = (JsonObject) v;
970-
final var status = ((JsonString) obj.members().get("status")).value();
971-
return "DIFFERENT".equals(status);
972-
})
973-
.toList();
968+
final var stableLines = new ArrayList<String>();
974969

975-
// Serialize to stable JSON string for hashing
976-
final var jsonString = JsonArray.of(diffsOnly).toString();
970+
for (final var diff : differences.values()) {
971+
final var diffObj = (JsonObject) diff;
972+
final var status = ((JsonString) diffObj.members().get("status")).value();
973+
974+
if (!"DIFFERENT".equals(status)) continue;
975+
976+
final var className = ((JsonString) diffObj.members().get("className")).value();
977+
final var classDiffs = (JsonArray) diffObj.members().get("differences");
978+
979+
if (classDiffs != null) {
980+
for (final var change : classDiffs.values()) {
981+
final var changeObj = (JsonObject) change;
982+
final var type = ((JsonString) changeObj.members().get("type")).value();
983+
final var methodValue = changeObj.members().get("method");
984+
final var method = methodValue instanceof JsonString js ? js.value() : "";
985+
// Create stable line: "ClassName:changeType:methodName"
986+
stableLines.add(className + ":" + type + ":" + method);
987+
}
988+
}
989+
}
990+
991+
// Sort for deterministic ordering
992+
Collections.sort(stableLines);
993+
final var stableString = String.join("\n", stableLines);
977994

978995
try {
979996
final var digest = MessageDigest.getInstance("SHA-256");
980-
final var hash = digest.digest(jsonString.getBytes(StandardCharsets.UTF_8));
997+
final var hash = digest.digest(stableString.getBytes(StandardCharsets.UTF_8));
981998
final var hexString = new StringBuilder();
982999
for (final var b : hash) {
9831000
hexString.append(String.format("%02x", b));
9841001
}
9851002
return hexString.substring(0, 7);
9861003
} catch (NoSuchAlgorithmException e) {
9871004
LOGGER.warning("SHA-256 not available, using fallback fingerprint");
988-
return String.format("%07d", jsonString.hashCode() & 0xFFFFFFF);
1005+
return String.format("%07d", stableString.hashCode() & 0xFFFFFFF);
9891006
}
9901007
}
9911008

0 commit comments

Comments
 (0)