19
19
import java .io .IOException ;
20
20
import java .io .ObjectInputStream ;
21
21
import java .io .ObjectOutputStream ;
22
+ import java .nio .file .Path ;
23
+ import java .util .Comparator ;
22
24
import java .util .HashMap ;
23
25
import java .util .Map ;
24
26
import java .util .function .Consumer ;
31
33
import org .gradle .api .artifacts .dsl .RepositoryHandler ;
32
34
import org .gradle .testfixtures .ProjectBuilder ;
33
35
34
- import com .diffplug .common .base .Box ;
35
36
import com .diffplug .common .base .Errors ;
36
37
import com .diffplug .common .base .StandardSystemProperty ;
37
38
import com .diffplug .common .base .Suppliers ;
38
39
import com .diffplug .common .collect .ImmutableSet ;
39
40
import com .diffplug .common .io .Files ;
40
41
41
42
public class TestProvisioner {
43
+ public static Project gradleProject (File dir ) {
44
+ File userHome = new File (StandardSystemProperty .USER_HOME .value ());
45
+ return ProjectBuilder .builder ()
46
+ .withGradleUserHomeDir (new File (userHome , ".gradle" ))
47
+ .withProjectDir (dir )
48
+ .build ();
49
+ }
50
+
42
51
/**
43
52
* Creates a Provisioner for the given repositories.
44
53
*
@@ -47,26 +56,35 @@ public class TestProvisioner {
47
56
*
48
57
* Every call to resolve will take about 1 second, even when all artifacts are resolved.
49
58
*/
50
- private static Supplier < Provisioner > createLazyWithRepositories (Consumer <RepositoryHandler > repoConfig ) {
59
+ private static Provisioner createWithRepositories (Consumer <RepositoryHandler > repoConfig ) {
51
60
// Running this takes ~3 seconds the first time it is called. Probably because of classloading.
52
- return Suppliers .memoize (() -> {
53
- Project project = ProjectBuilder .builder ().build ();
54
- repoConfig .accept (project .getRepositories ());
55
- return (withTransitives , mavenCoords ) -> {
56
- Dependency [] deps = mavenCoords .stream ()
57
- .map (project .getDependencies ()::create )
58
- .toArray (Dependency []::new );
59
- Configuration config = project .getConfigurations ().detachedConfiguration (deps );
60
- config .setTransitive (withTransitives );
61
- config .setDescription (mavenCoords .toString ());
61
+ File tempDir = Files .createTempDir ();
62
+ Project project = TestProvisioner .gradleProject (tempDir );
63
+ repoConfig .accept (project .getRepositories ());
64
+ return (withTransitives , mavenCoords ) -> {
65
+ Dependency [] deps = mavenCoords .stream ()
66
+ .map (project .getDependencies ()::create )
67
+ .toArray (Dependency []::new );
68
+ Configuration config = project .getConfigurations ().detachedConfiguration (deps );
69
+ config .setTransitive (withTransitives );
70
+ config .setDescription (mavenCoords .toString ());
71
+ try {
72
+ return config .resolve ();
73
+ } catch (ResolveException e ) {
74
+ /* Provide Maven coordinates in exception message instead of static string 'detachedConfiguration' */
75
+ throw new ResolveException (config .getDescription (), e );
76
+ } finally {
77
+ // delete the temp dir
62
78
try {
63
- return config .resolve ();
64
- } catch (ResolveException e ) {
65
- /* Provide Maven coordinates in exception message instead of static string 'detachedConfiguration' */
66
- throw new ResolveException (config .getDescription (), e );
79
+ java .nio .file .Files .walk (tempDir .toPath ())
80
+ .sorted (Comparator .reverseOrder ())
81
+ .map (Path ::toFile )
82
+ .forEach (File ::delete );
83
+ } catch (IOException e ) {
84
+ throw Errors .asRuntime (e );
67
85
}
68
- };
69
- }) ;
86
+ }
87
+ };
70
88
}
71
89
72
90
/** Creates a Provisioner which will cache the result of previous calls. */
@@ -86,20 +104,23 @@ private static Provisioner caching(String name, Supplier<Provisioner> input) {
86
104
} else {
87
105
cached = new HashMap <>();
88
106
}
89
- return (withTransitives , mavenCoords ) -> {
90
- Box <Boolean > wasChanged = Box .of (false );
91
- ImmutableSet <File > result = cached .computeIfAbsent (ImmutableSet .copyOf (mavenCoords ), coords -> {
92
- wasChanged .set (true );
93
- return ImmutableSet .copyOf (input .get ().provisionWithTransitives (withTransitives , coords ));
94
- });
95
- if (wasChanged .get ()) {
96
- try (ObjectOutputStream outputStream = new ObjectOutputStream (Files .asByteSink (cacheFile ).openBufferedStream ())) {
97
- outputStream .writeObject (cached );
98
- } catch (IOException e ) {
99
- throw Errors .asRuntime (e );
107
+ return (withTransitives , mavenCoordsRaw ) -> {
108
+ ImmutableSet <String > mavenCoords = ImmutableSet .copyOf (mavenCoordsRaw );
109
+ synchronized (TestProvisioner .class ) {
110
+ ImmutableSet <File > result = cached .get (mavenCoords );
111
+ // double-check that depcache pruning hasn't removed them since our cache cached them
112
+ boolean needsToBeSet = result == null || !result .stream ().allMatch (file -> file .exists () && file .isFile () && file .length () > 0 );
113
+ if (needsToBeSet ) {
114
+ result = ImmutableSet .copyOf (input .get ().provisionWithTransitives (withTransitives , mavenCoords ));
115
+ cached .put (mavenCoords , result );
116
+ try (ObjectOutputStream outputStream = new ObjectOutputStream (Files .asByteSink (cacheFile ).openBufferedStream ())) {
117
+ outputStream .writeObject (cached );
118
+ } catch (IOException e ) {
119
+ throw Errors .asRuntime (e );
120
+ }
100
121
}
122
+ return result ;
101
123
}
102
- return result ;
103
124
};
104
125
}
105
126
@@ -109,7 +130,7 @@ public static Provisioner jcenter() {
109
130
}
110
131
111
132
private static final Supplier <Provisioner > jcenter = Suppliers .memoize (() -> {
112
- return caching ("jcenter" , createLazyWithRepositories (repo -> repo .jcenter ()));
133
+ return caching ("jcenter" , () -> createWithRepositories (repo -> repo .jcenter ()));
113
134
});
114
135
115
136
/** Creates a Provisioner for the mavenCentral repo. */
@@ -118,22 +139,22 @@ public static Provisioner mavenCentral() {
118
139
}
119
140
120
141
private static final Supplier <Provisioner > mavenCentral = Suppliers .memoize (() -> {
121
- return caching ("mavenCentral" , createLazyWithRepositories (repo -> repo .mavenCentral ()));
142
+ return caching ("mavenCentral" , () -> createWithRepositories (repo -> repo .mavenCentral ()));
122
143
});
123
144
124
145
/** Creates a Provisioner for the local maven repo for development purpose. */
125
146
public static Provisioner mavenLocal () {
126
147
return mavenLocal .get ();
127
148
}
128
149
129
- private static final Supplier <Provisioner > mavenLocal = createLazyWithRepositories (repo -> repo .mavenLocal ());
150
+ private static final Supplier <Provisioner > mavenLocal = () -> createWithRepositories (repo -> repo .mavenLocal ());
130
151
131
152
/** Creates a Provisioner for the Sonatype snapshots maven repo for development purpose. */
132
153
public static Provisioner snapshots () {
133
154
return snapshots .get ();
134
155
}
135
156
136
- private static final Supplier <Provisioner > snapshots = createLazyWithRepositories (repo -> {
157
+ private static final Supplier <Provisioner > snapshots = () -> createWithRepositories (repo -> {
137
158
repo .maven (setup -> {
138
159
setup .setUrl ("https://oss.sonatype.org/content/repositories/snapshots" );
139
160
});
0 commit comments