Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 3 blank lines between lock entries to minimize merge conflicts #1001

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Direct dependencies are specified in a top level `versions.props` file and then
4. Run **`./gradlew --write-locks`** and see your versions.lock file be automatically created. This file should be checked into your repo:

```bash
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note from internal discussion about this. I think the idea is good but the tricky bit is the rollout, especially as we have external users of this plugin since it's open source and there are consumers who read the lock file, who may not skip empty lines.

I think the only real way to do this is to have a feature flag in gradle.properties (or somewhere else) to write out the new file with the extra blank lines. Still support the old version. Then we can have an excavator internally which applies this to every repo one by one. We can find and fix consumers as it rolls out. External people can opt in but are not affected.

Maybe some time in the future make a major version bump that changes the default - but only maybe.

com.squareup.okhttp3:okhttp:3.12.0 (1 constraints: 38053b3b)
com.squareup.okio:okio:1.15.0 (1 constraints: 810cbb09)
```
Expand Down
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-1001.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Add 3 blank lines between lock entries to minimize merge conflicts
links:
- https://github.com/palantir/gradle-consistent-versions/pull/1001
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
import org.gradle.api.GradleException;

final class ConflictSafeLockFile {
private static final String HEADER_COMMENT = "# Run ./gradlew --write-locks to regenerate this file";
private static final String HEADER_COMMENT =
"# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.";
private static final Pattern LINE_PATTERN =
Pattern.compile("(?<group>[^(:]+):(?<artifact>[^(:]+):(?<version>[^(:\\s]+)"
+ "\\s+\\((?<num>\\d+) constraints: (?<hash>\\w+)\\)");
Expand All @@ -49,16 +50,14 @@ final class ConflictSafeLockFile {

/** Reads and returns the {@link LockState}. */
public LockState readLocks() {
try (Stream<String> linesStream = Files.lines(lockfile)) {
try (Stream<String> linesStream = Files.lines(lockfile).filter(line -> !line.isBlank())) {
List<String> lines =
linesStream.filter(line -> !line.trim().startsWith("#")).collect(Collectors.toList());
int testDependenciesPosition = lines.indexOf(TEST_DEPENDENCIES_MARKER);
Stream<String> productionDeps;
Stream<String> testDeps;
if (testDependenciesPosition >= 0) {
productionDeps = lines
.subList(0, testDependenciesPosition - 1) // skip blank line before marker
.stream();
if (testDependenciesPosition >= 0 && testDependenciesPosition + 1 < lines.size()) {
productionDeps = lines.subList(0, testDependenciesPosition).stream();
testDeps = lines.subList(testDependenciesPosition + 1, lines.size()).stream();
} else {
productionDeps = lines.stream().filter(line -> !line.trim().startsWith("#"));
Expand All @@ -74,6 +73,7 @@ public LockState readLocks() {

public Stream<Line> parseLines(Stream<String> stringStream) {
return stringStream
.filter(line -> !line.isBlank())
.map(line -> {
Matcher matcher = LINE_PATTERN.matcher(line);
Preconditions.checkState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ private static String formatDependencyDifferences(Map<MyModuleIdentifier, ValueD
"" // to align strings
+ "-%s\n"
+ "+%s",
diff.getValue().leftValue().stringRepresentation(),
diff.getValue().rightValue().stringRepresentation()))
diff.getValue().leftValue().lockLine(),
diff.getValue().rightValue().lockLine()))
.collect(Collectors.joining("\n"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ default MyModuleIdentifier identifier() {

@Lazy
default String stringRepresentation() {
return String.format(
"%s:%s:%s (%s constraints: %s)", group(), name(), version(), numDependents(), dependentsHash());
// Three blank lines to avoid conflicts with automated upgrades
return "\n\n\n" + lockLine();
}

default String lockLine() {
return group() + ':' + name() + ':' + version() + " (" + numDependents() + " constraints: " + dependentsHash()
+ ')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private static Line componentWithDependentsToLine(ModuleVersionIdentifier compon

Line line = ImmutableLine.of(
component.getGroup(), component.getName(), component.getVersion(), all.size(), hash.toString());
log.info("{}: {}", line.stringRepresentation(), all);
log.info("{}: {}", line.lockLine(), all);
return line;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,14 @@ class ConsistentVersionsPluginIntegrationSpec extends IntegrationSpec {

then:
def expectedLock = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



test-alignment:module-that-should-be-aligned-up:1.1 (1 constraints: a5041a2c)



test-alignment:module-with-higher-version:1.1 (1 constraints: a6041b2c)
""".stripIndent()
file('versions.lock').text == expectedLock
Expand Down Expand Up @@ -276,7 +282,10 @@ class ConsistentVersionsPluginIntegrationSpec extends IntegrationSpec {

then:
def expectedLock = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



org.slf4j:slf4j-api:1.7.25 (1 constraints: 4105483b)
""".stripIndent()
file('versions.lock').text == expectedLock
Expand Down Expand Up @@ -334,9 +343,18 @@ class ConsistentVersionsPluginIntegrationSpec extends IntegrationSpec {
runTasks('--write-locks')

file('versions.lock').text == """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



org.slf4j:slf4j-api:1.7.25 (1 constraints: 4105483b)



org1:platform:1.0 (1 constraints: a5041a2c)



org2:platform:1.0 (1 constraints: a5041a2c)
""".stripIndent()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,10 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {

then:
file('versions.lock').readLines() == [
'# Run ./gradlew --write-locks to regenerate this file',
'# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.',
'',
'',
'',
'org:platform:1.0 (1 constraints: a5041a2c)',
]

Expand Down Expand Up @@ -687,8 +690,14 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {

then: 'slf4j-api still appears in the lock file'
file('versions.lock').readLines() == [
'# Run ./gradlew --write-locks to regenerate this file',
'# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.',
'',
'',
'',
'ch.qos.logback:logback-classic:1.2.3 (1 constraints: 0805f935)',
'',
'',
'',
'org.slf4j:slf4j-api:1.7.25 (1 constraints: 400d4d2a)',
]

Expand Down Expand Up @@ -774,11 +783,20 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
expect:
runTasks('--write-locks')
def expected = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



ch.qos.logback:logback-classic:1.2.3 (1 constraints: 0805f935)



org.slf4j:slf4j-api:1.7.25 (2 constraints: 7917e690)

[Test dependencies]



org:test-dep-that-logs:1.0 (1 constraints: a5041a2c)
""".stripIndent()
file('versions.lock').text == expected
Expand Down Expand Up @@ -806,12 +824,24 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
expect:
runTasks('--write-locks')
def expected = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



ch.qos.logback:logback-classic:1.2.3 (1 constraints: 0805f935)



org.slf4j:slf4j-api:1.7.25 (2 constraints: 7917e690)

[Test dependencies]



junit:junit:4.10 (1 constraints: d904fd30)



org:test-dep-that-logs:1.0 (1 constraints: a5041a2c)
""".stripIndent()
file('versions.lock').text == expected
Expand All @@ -836,9 +866,12 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
expect:
runTasks('--write-locks')
def expected = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.

[Test dependencies]



junit:junit:4.10 (1 constraints: d904fd30)
""".stripIndent()
file('versions.lock').text == expected
Expand Down Expand Up @@ -866,10 +899,16 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
expect:
runTasks('--write-locks')
def expected = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.

[Test dependencies]



ch.qos.logback:logback-classic:1.2.3 (1 constraints: 0805f935)



org.slf4j:slf4j-api:1.7.25 (1 constraints: 400d4d2a)
""".stripIndent()
file('versions.lock').text == expected
Expand Down Expand Up @@ -1098,8 +1137,14 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
expect:
runTasks("--write-locks")
file('versions.lock').text == """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.



ch.qos.logback:logback-classic:1.2.3 (1 constraints: 0805f935)



org.slf4j:slf4j-api:1.7.25 (2 constraints: 8012a437)
""".stripIndent()

Expand All @@ -1118,7 +1163,7 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec {
""".stripIndent()

def lockFileContent = """\
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.
""".stripIndent()

file('versions.lock').text = lockFileContent
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/sample-versions.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Run ./gradlew --write-locks to regenerate this file
# Run ./gradlew --write-locks to regenerate this file. Blank lines are to minimize merge conflicts.
aopalliance:aopalliance:1.0 (1 constraints: 170a83ac)
ch.qos.logback:logback-access:1.2.3 (3 constraints: 4f354f15)
ch.qos.logback:logback-classic:1.2.3 (5 constraints: 9351d6aa)
Expand Down