Skip to content

Commit 082f867

Browse files
committed
Add a new GitAttributesLineEndings.Policy which relativizes all paths against the projectDir, and does not rely on FileSignature at all.
1 parent 2c68977 commit 082f867

1 file changed

Lines changed: 65 additions & 2 deletions

File tree

lib-extra/src/main/java/com/diffplug/spotless/extra/GitAttributesLineEndings.java

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 DiffPlug
2+
* Copyright 2016-2020 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -72,7 +72,70 @@ public final class GitAttributesLineEndings {
7272
// prevent direct instantiation
7373
private GitAttributesLineEndings() {}
7474

75-
public static Policy create(File projectDir, Supplier<Iterable<File>> toFormat) {
75+
/**
76+
* Creates a line-endings policy whose serialized state is relativized against projectDir,
77+
* at the cost of eagerly evaluating the line-ending state of every target file.
78+
*/
79+
public static LineEnding.Policy createRelocatable(File projectDir, Supplier<Iterable<File>> toFormat) {
80+
return new RelocatablePolicy(projectDir, toFormat);
81+
}
82+
83+
static class RelocatablePolicy extends LazyForwardingEquality<CachedEndings> implements LineEnding.Policy {
84+
private static final long serialVersionUID = 5868522122123693015L;
85+
86+
final transient File projectDir;
87+
final transient Supplier<Iterable<File>> toFormat;
88+
89+
RelocatablePolicy(File projectDir, Supplier<Iterable<File>> toFormat) {
90+
this.projectDir = Objects.requireNonNull(projectDir, "projectDir");
91+
this.toFormat = Objects.requireNonNull(toFormat, "toFormat");
92+
}
93+
94+
@Override
95+
protected CachedEndings calculateState() throws Exception {
96+
Runtime runtime = new FileState(projectDir, toFormat.get()).atRuntime();
97+
return new CachedEndings(projectDir, runtime, toFormat.get());
98+
}
99+
100+
@Override
101+
public String getEndingFor(File file) {
102+
return state().endingFor(file);
103+
}
104+
}
105+
106+
static class CachedEndings implements Serializable {
107+
private static final long serialVersionUID = -2534772773057900619L;
108+
109+
/** this is transient, to simulate PathSensitive.RELATIVE */
110+
transient final String rootDir;
111+
/** the line ending used for most files */
112+
final String defaultEnding;
113+
/** any exceptions to that default, in terms of relative path from rootDir */
114+
final ConcurrentRadixTree<String> hasNonDefaultEnding = new ConcurrentRadixTree<>(new DefaultCharSequenceNodeFactory());
115+
116+
CachedEndings(File projectDir, Runtime runtime, Iterable<File> toFormat) {
117+
rootDir = FileSignature.pathNativeToUnix(projectDir.getAbsolutePath()) + "/";
118+
defaultEnding = runtime.defaultEnding;
119+
for (File file : toFormat) {
120+
String ending = runtime.getEndingFor(file);
121+
if (!ending.equals(defaultEnding)) {
122+
String path = FileSignature.pathNativeToUnix(file.getAbsolutePath());
123+
hasNonDefaultEnding.put(path, ending);
124+
}
125+
}
126+
}
127+
128+
/** Returns the line ending appropriate for the given file. */
129+
public String endingFor(File file) {
130+
String path = FileSignature.pathNativeToUnix(file.getAbsolutePath());
131+
String subpath = FileSignature.subpath(rootDir, path);
132+
String ending = hasNonDefaultEnding.getValueForExactKey(subpath);
133+
return ending == null ? defaultEnding : ending;
134+
}
135+
}
136+
137+
/** Creates a line-endings policy whose serialized state includes absolute paths to this machine. */
138+
public static LineEnding.Policy create(File projectDir, Supplier<Iterable<File>> toFormat) {
76139
return new Policy(projectDir, toFormat);
77140
}
78141

0 commit comments

Comments
 (0)