embulk-output-multi 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/gradle.properties +1 -1
- data/src/main/java/org/embulk/output/multi/AsyncRunControl.java +6 -10
- data/src/main/java/org/embulk/output/multi/MultiOutputPlugin.java +33 -18
- data/src/main/java/org/embulk/output/multi/OutputPluginDelegate.java +43 -41
- data/src/main/java/org/embulk/output/multi/TaskReports.java +6 -6
- data/src/main/java/org/embulk/output/multi/TransactionalPageOutputDelegate.java +5 -1
- data/src/test/java/org/embulk/output/multi/TestMultiOutputPlugin.java +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 133f0b4290cb49bc787590e22edacf2e4f4df4e1
|
4
|
+
data.tar.gz: bb8c9a01232bb0ab43bc845af45a66039988133d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a63b03b9c0d566b49c88fb666390d94ddab230ef21d1fe4254f7131fc4fb6977610b6b95d9966e98631ec8d842dbdcbfc1639d076f6f7bd394f076a4dbe913d
|
7
|
+
data.tar.gz: 754f5fe52bb5b00f87eebdbaef36157dc4d1e9c1ddcbc541f66d9d6cb54af134c02010a50684f5114a3107ea2dfb2f3ec087807da5aa2b411e13bbd2d1889f7a
|
data/gradle.properties
CHANGED
@@ -1 +1 @@
|
|
1
|
-
version=0.2.
|
1
|
+
version=0.2.2
|
@@ -5,22 +5,22 @@ import org.embulk.config.TaskReport;
|
|
5
5
|
import org.embulk.config.TaskSource;
|
6
6
|
import org.embulk.spi.OutputPlugin;
|
7
7
|
|
8
|
-
import java.util.ArrayList;
|
9
8
|
import java.util.List;
|
10
9
|
import java.util.concurrent.Callable;
|
10
|
+
import java.util.concurrent.ConcurrentHashMap;
|
11
|
+
import java.util.concurrent.ConcurrentMap;
|
11
12
|
import java.util.concurrent.CountDownLatch;
|
12
13
|
import java.util.concurrent.ExecutionException;
|
13
14
|
import java.util.concurrent.ExecutorService;
|
14
15
|
import java.util.concurrent.Executors;
|
15
16
|
import java.util.concurrent.Future;
|
16
|
-
import java.util.concurrent.atomic.AtomicReferenceArray;
|
17
17
|
|
18
18
|
class AsyncRunControl {
|
19
19
|
private static final String THREAD_NAME_FORMAT = "multi-run-control-%d";
|
20
20
|
private final MultiOutputPlugin.PluginTask task;
|
21
21
|
private final OutputPlugin.Control control;
|
22
22
|
private final CountDownLatch latch;
|
23
|
-
private final
|
23
|
+
private final ConcurrentMap<String, TaskSource> taskSources;
|
24
24
|
private final ExecutorService executorService;
|
25
25
|
private Future<List<TaskReport>> result;
|
26
26
|
|
@@ -32,7 +32,7 @@ class AsyncRunControl {
|
|
32
32
|
this.task = task;
|
33
33
|
this.control = control;
|
34
34
|
this.latch = new CountDownLatch(task.getOutputConfigs().size());
|
35
|
-
this.taskSources = new
|
35
|
+
this.taskSources = new ConcurrentHashMap<>(task.getOutputConfigs().size());
|
36
36
|
this.executorService = Executors.newSingleThreadExecutor(
|
37
37
|
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME_FORMAT).build()
|
38
38
|
);
|
@@ -42,8 +42,8 @@ class AsyncRunControl {
|
|
42
42
|
result.cancel(true);
|
43
43
|
}
|
44
44
|
|
45
|
-
void addTaskSource(
|
46
|
-
taskSources.
|
45
|
+
void addTaskSource(String tag, TaskSource taskSource) {
|
46
|
+
taskSources.putIfAbsent(tag, taskSource);
|
47
47
|
latch.countDown();
|
48
48
|
}
|
49
49
|
|
@@ -64,10 +64,6 @@ class AsyncRunControl {
|
|
64
64
|
@Override
|
65
65
|
public List<TaskReport> call() throws Exception {
|
66
66
|
latch.await();
|
67
|
-
List<TaskSource> taskSources = new ArrayList<>(AsyncRunControl.this.taskSources.length());
|
68
|
-
for (int i = 0; i < AsyncRunControl.this.taskSources.length(); i++) {
|
69
|
-
taskSources.add(AsyncRunControl.this.taskSources.get(i));
|
70
|
-
}
|
71
67
|
task.setTaskSources(taskSources);
|
72
68
|
return control.run(task.dump());
|
73
69
|
}
|
@@ -16,12 +16,15 @@ import org.embulk.spi.OutputPlugin;
|
|
16
16
|
import org.embulk.spi.Page;
|
17
17
|
import org.embulk.spi.Schema;
|
18
18
|
import org.embulk.spi.TransactionalPageOutput;
|
19
|
+
import org.slf4j.Logger;
|
20
|
+
import org.slf4j.LoggerFactory;
|
19
21
|
|
20
22
|
import java.util.ArrayList;
|
23
|
+
import java.util.HashMap;
|
21
24
|
import java.util.List;
|
25
|
+
import java.util.Map;
|
22
26
|
import java.util.Optional;
|
23
27
|
import java.util.concurrent.ExecutionException;
|
24
|
-
import java.util.concurrent.Future;
|
25
28
|
import java.util.function.Function;
|
26
29
|
import java.util.stream.Collectors;
|
27
30
|
|
@@ -32,12 +35,13 @@ public class MultiOutputPlugin implements OutputPlugin {
|
|
32
35
|
|
33
36
|
@Config(CONFIG_NAME_OUTPUT_CONFIG_DIFFS)
|
34
37
|
@ConfigDefault("null")
|
35
|
-
Optional<
|
38
|
+
Optional<Map<String, ConfigDiff>> getOutputConfigDiffs();
|
36
39
|
|
37
|
-
|
38
|
-
void setTaskSources(
|
40
|
+
Map<String, TaskSource> getTaskSources();
|
41
|
+
void setTaskSources(Map<String, TaskSource> taskSources);
|
39
42
|
}
|
40
43
|
|
44
|
+
private static final Logger LOGGER = LoggerFactory.getLogger(MultiOutputPlugin.class);
|
41
45
|
private static final String CONFIG_NAME_OUTPUT_CONFIG_DIFFS = "output_config_diffs";
|
42
46
|
static final String CONFIG_NAME_OUTPUT_TASK_REPORTS = "output_task_reports";
|
43
47
|
|
@@ -123,11 +127,11 @@ public class MultiOutputPlugin implements OutputPlugin {
|
|
123
127
|
@Override
|
124
128
|
public TaskReport commit() {
|
125
129
|
final TaskReport report = Exec.newTaskReport();
|
126
|
-
final
|
130
|
+
final Map<String, TaskReport> reports = new HashMap<>();
|
127
131
|
final List<OutputPluginDelegate> errorPlugins = new ArrayList<>();
|
128
132
|
for (TransactionalPageOutputDelegate output : delegates) {
|
129
133
|
try {
|
130
|
-
reports.
|
134
|
+
reports.put(output.getTag(), output.commit());
|
131
135
|
} catch (PluginExecutionException e) {
|
132
136
|
errorPlugins.add(e.getPlugin());
|
133
137
|
}
|
@@ -135,7 +139,7 @@ public class MultiOutputPlugin implements OutputPlugin {
|
|
135
139
|
if (!errorPlugins.isEmpty()) {
|
136
140
|
throw new RuntimeException(
|
137
141
|
String.format("Following plugins failed to output [%s]",
|
138
|
-
errorPlugins.stream().map(OutputPluginDelegate::
|
142
|
+
errorPlugins.stream().map(OutputPluginDelegate::getTag).collect(Collectors.joining(", "))
|
139
143
|
));
|
140
144
|
}
|
141
145
|
report.set(CONFIG_NAME_OUTPUT_TASK_REPORTS, new TaskReports(reports));
|
@@ -144,12 +148,12 @@ public class MultiOutputPlugin implements OutputPlugin {
|
|
144
148
|
};
|
145
149
|
}
|
146
150
|
|
147
|
-
private static ConfigDiff buildConfigDiff(List<
|
151
|
+
private static ConfigDiff buildConfigDiff(List<OutputPluginDelegate.Transaction> transactions) {
|
148
152
|
final ConfigDiff configDiff = Exec.newConfigDiff();
|
149
|
-
|
150
|
-
for (
|
153
|
+
Map<String, ConfigDiff> configDiffs = new HashMap<>();
|
154
|
+
for (OutputPluginDelegate.Transaction transaction: transactions) {
|
151
155
|
try {
|
152
|
-
configDiffs.
|
156
|
+
configDiffs.put(transaction.getTag(), transaction.getResult());
|
153
157
|
} catch (InterruptedException e) {
|
154
158
|
Thread.currentThread().interrupt();
|
155
159
|
throw new RuntimeException(e);
|
@@ -163,18 +167,29 @@ public class MultiOutputPlugin implements OutputPlugin {
|
|
163
167
|
|
164
168
|
private <T> List<T> mapWithPluginDelegate(PluginTask task, ExecSession session, Function<OutputPluginDelegate, T> action) {
|
165
169
|
List<T> result = new ArrayList<>();
|
166
|
-
for (int
|
167
|
-
final ConfigSource config = task.getOutputConfigs().get(
|
168
|
-
if (task.getOutputConfigDiffs().isPresent()) {
|
169
|
-
config.merge(task.getOutputConfigDiffs().get().get(pluginIndex));
|
170
|
-
}
|
170
|
+
for (int i = 0; i < task.getOutputConfigs().size(); i++) {
|
171
|
+
final ConfigSource config = task.getOutputConfigs().get(i);
|
171
172
|
final PluginType pluginType = config.get(PluginType.class, "type");
|
172
173
|
final OutputPlugin outputPlugin = session.newPlugin(OutputPlugin.class, pluginType);
|
174
|
+
|
175
|
+
final String tag = String.format("%s_%d", pluginType.getName(), i);
|
176
|
+
|
177
|
+
// Merge ConfigDiff if exists
|
178
|
+
if (task.getOutputConfigDiffs().isPresent()) {
|
179
|
+
final ConfigDiff configDiff = task.getOutputConfigDiffs().get().get(tag);
|
180
|
+
if (configDiff != null) {
|
181
|
+
config.merge(configDiff);
|
182
|
+
} else {
|
183
|
+
LOGGER.debug("ConfigDiff for '{}' not found.", tag);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
// Set TaskSource if exists
|
173
187
|
TaskSource taskSource = null;
|
174
188
|
if (task.getTaskSources() != null) {
|
175
|
-
taskSource = task.getTaskSources().get(
|
189
|
+
taskSource = task.getTaskSources().get(tag);
|
176
190
|
}
|
177
|
-
|
191
|
+
|
192
|
+
result.add(action.apply(new OutputPluginDelegate(tag, outputPlugin, config, taskSource)));
|
178
193
|
}
|
179
194
|
return result;
|
180
195
|
}
|
@@ -5,7 +5,6 @@ import org.embulk.config.ConfigDiff;
|
|
5
5
|
import org.embulk.config.ConfigSource;
|
6
6
|
import org.embulk.config.TaskReport;
|
7
7
|
import org.embulk.config.TaskSource;
|
8
|
-
import org.embulk.plugin.PluginType;
|
9
8
|
import org.embulk.spi.OutputPlugin;
|
10
9
|
import org.embulk.spi.Schema;
|
11
10
|
import org.embulk.spi.TransactionalPageOutput;
|
@@ -23,105 +22,92 @@ import java.util.concurrent.Future;
|
|
23
22
|
class OutputPluginDelegate {
|
24
23
|
private static final Logger LOGGER = LoggerFactory.getLogger(OutputPluginDelegate.class);
|
25
24
|
private static final String THREAD_NAME_FORMAT = "multi-output-plugin-%s-%%d";
|
26
|
-
private final
|
27
|
-
private final PluginType type;
|
25
|
+
private final String tag;
|
28
26
|
private final OutputPlugin plugin;
|
29
27
|
private final ConfigSource config;
|
30
28
|
private final TaskSource taskSource;
|
31
29
|
private final ExecutorService executorService;
|
32
30
|
|
33
31
|
OutputPluginDelegate(
|
34
|
-
|
35
|
-
PluginType type,
|
32
|
+
String tag,
|
36
33
|
OutputPlugin plugin,
|
37
34
|
ConfigSource config,
|
38
35
|
TaskSource taskSource
|
39
36
|
) {
|
40
|
-
this.
|
41
|
-
this.type = type;
|
37
|
+
this.tag = tag;
|
42
38
|
this.plugin = plugin;
|
43
39
|
this.config = config;
|
44
40
|
this.taskSource = taskSource;
|
45
41
|
this.executorService = Executors.newSingleThreadExecutor(
|
46
|
-
new ThreadFactoryBuilder().setNameFormat(String.format(THREAD_NAME_FORMAT,
|
42
|
+
new ThreadFactoryBuilder().setNameFormat(String.format(THREAD_NAME_FORMAT, tag)).build()
|
47
43
|
);
|
48
44
|
}
|
49
45
|
|
50
|
-
|
51
|
-
return executorService.submit(() -> {
|
46
|
+
Transaction transaction(Schema schema, int taskCount, AsyncRunControl runControl) {
|
47
|
+
return new Transaction(executorService.submit(() -> {
|
52
48
|
try {
|
53
|
-
LOGGER.debug("Run #transaction for {}",
|
54
|
-
return plugin.transaction(config, schema, taskCount, new Control(
|
49
|
+
LOGGER.debug("Run #transaction for {}", getTag());
|
50
|
+
return plugin.transaction(config, schema, taskCount, new Control(runControl));
|
55
51
|
} catch (CancellationException e) {
|
56
|
-
LOGGER.error("Canceled #transaction for {} by other plugin's error",
|
52
|
+
LOGGER.error("Canceled #transaction for {} by other plugin's error", getTag());
|
57
53
|
throw e;
|
58
54
|
} catch (Exception e) {
|
59
|
-
LOGGER.error("Transaction for {} failed.",
|
55
|
+
LOGGER.error("Transaction for {} failed.", getTag(), e);
|
60
56
|
runControl.cancel();
|
61
57
|
throw e;
|
62
58
|
} finally {
|
63
59
|
executorService.shutdown();
|
64
60
|
}
|
65
|
-
});
|
61
|
+
}));
|
66
62
|
}
|
67
63
|
|
68
|
-
|
69
|
-
return executorService.submit(() -> {
|
64
|
+
Transaction resume(Schema schema, int taskCount, AsyncRunControl runControl) {
|
65
|
+
return new Transaction(executorService.submit(() -> {
|
70
66
|
try {
|
71
|
-
LOGGER.debug("Run #resume for {}",
|
72
|
-
return plugin.resume(taskSource, schema, taskCount, new Control(
|
67
|
+
LOGGER.debug("Run #resume for {}", getTag());
|
68
|
+
return plugin.resume(taskSource, schema, taskCount, new Control(runControl));
|
73
69
|
} catch (CancellationException e) {
|
74
|
-
LOGGER.error("Canceled #resume for {} by other plugin's error",
|
70
|
+
LOGGER.error("Canceled #resume for {} by other plugin's error", getTag());
|
75
71
|
throw e;
|
76
72
|
} catch (Exception e) {
|
77
|
-
LOGGER.error("Resume for {} failed.",
|
73
|
+
LOGGER.error("Resume for {} failed.", getTag(), e);
|
78
74
|
runControl.cancel();
|
79
75
|
throw e;
|
80
76
|
} finally {
|
81
77
|
executorService.shutdown();
|
82
78
|
}
|
83
|
-
});
|
79
|
+
}));
|
84
80
|
}
|
85
81
|
|
86
82
|
void cleanup(Schema schema, int taskCount, List<TaskReport> successTaskReports) {
|
87
|
-
LOGGER.debug("Run #cleanup for {}",
|
83
|
+
LOGGER.debug("Run #cleanup for {}", getTag());
|
88
84
|
List<TaskReport> successReportsForPlugin = new ArrayList<>();
|
89
85
|
for (TaskReport successTaskReport : successTaskReports) {
|
90
|
-
final TaskReport report = successTaskReport.get(TaskReports.class, MultiOutputPlugin.CONFIG_NAME_OUTPUT_TASK_REPORTS).get(
|
86
|
+
final TaskReport report = successTaskReport.get(TaskReports.class, MultiOutputPlugin.CONFIG_NAME_OUTPUT_TASK_REPORTS).get(tag);
|
91
87
|
successReportsForPlugin.add(report);
|
92
88
|
}
|
93
89
|
plugin.cleanup(taskSource, schema, taskCount, successReportsForPlugin);
|
94
90
|
}
|
95
91
|
|
96
92
|
TransactionalPageOutput open(Schema schema, int taskIndex) {
|
97
|
-
LOGGER.debug("Run #open for {}",
|
93
|
+
LOGGER.debug("Run #open for {}", getTag());
|
98
94
|
return plugin.open(taskSource, schema, taskIndex);
|
99
95
|
}
|
100
96
|
|
101
|
-
|
102
|
-
return
|
97
|
+
String getTag() {
|
98
|
+
return tag;
|
103
99
|
}
|
104
100
|
|
105
|
-
|
106
|
-
return generatePluginCode(type, pluginIndex);
|
107
|
-
}
|
108
|
-
|
109
|
-
private static String generatePluginCode(PluginType type, int pluginIndex) {
|
110
|
-
return String.format("%s-%d", type.getName(), pluginIndex);
|
111
|
-
}
|
112
|
-
|
113
|
-
private static class Control implements OutputPlugin.Control {
|
114
|
-
private final int pluginIndex;
|
101
|
+
private class Control implements OutputPlugin.Control {
|
115
102
|
private final AsyncRunControl runControl;
|
116
103
|
|
117
|
-
Control(
|
118
|
-
this.pluginIndex = index;
|
104
|
+
Control(AsyncRunControl runControl) {
|
119
105
|
this.runControl = runControl;
|
120
106
|
}
|
121
107
|
|
122
108
|
@Override
|
123
109
|
public List<TaskReport> run(TaskSource taskSource) {
|
124
|
-
runControl.addTaskSource(
|
110
|
+
runControl.addTaskSource(tag, taskSource);
|
125
111
|
List<TaskReport> reports;
|
126
112
|
try {
|
127
113
|
reports = runControl.waitAndGetResult();
|
@@ -134,10 +120,26 @@ class OutputPluginDelegate {
|
|
134
120
|
|
135
121
|
final List<TaskReport> result = new ArrayList<>();
|
136
122
|
for (TaskReport taskReport : reports) {
|
137
|
-
final TaskReport report = taskReport.get(TaskReports.class, MultiOutputPlugin.CONFIG_NAME_OUTPUT_TASK_REPORTS).get(
|
123
|
+
final TaskReport report = taskReport.get(TaskReports.class, MultiOutputPlugin.CONFIG_NAME_OUTPUT_TASK_REPORTS).get(tag);
|
138
124
|
result.add(report);
|
139
125
|
}
|
140
126
|
return result;
|
141
127
|
}
|
142
128
|
}
|
129
|
+
|
130
|
+
class Transaction {
|
131
|
+
private final Future<ConfigDiff> future;
|
132
|
+
|
133
|
+
private Transaction(Future<ConfigDiff> future) {
|
134
|
+
this.future = future;
|
135
|
+
}
|
136
|
+
|
137
|
+
String getTag() {
|
138
|
+
return OutputPluginDelegate.this.getTag();
|
139
|
+
}
|
140
|
+
|
141
|
+
ConfigDiff getResult() throws ExecutionException, InterruptedException {
|
142
|
+
return future.get();
|
143
|
+
}
|
144
|
+
}
|
143
145
|
}
|
@@ -4,22 +4,22 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
|
4
4
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
5
5
|
import org.embulk.config.TaskReport;
|
6
6
|
|
7
|
-
import java.util.
|
7
|
+
import java.util.Map;
|
8
8
|
|
9
9
|
class TaskReports {
|
10
|
-
private final
|
10
|
+
private final Map<String, TaskReport> reports;
|
11
11
|
|
12
12
|
@JsonCreator
|
13
|
-
TaskReports(@JsonProperty("reports")
|
13
|
+
TaskReports(@JsonProperty("reports") Map<String, TaskReport> reports) {
|
14
14
|
this.reports = reports;
|
15
15
|
}
|
16
16
|
|
17
17
|
@JsonProperty("reports")
|
18
|
-
|
18
|
+
Map<String, TaskReport> getReports() {
|
19
19
|
return reports;
|
20
20
|
}
|
21
21
|
|
22
|
-
TaskReport get(
|
23
|
-
return reports.get(
|
22
|
+
TaskReport get(String tag) {
|
23
|
+
return reports.get(tag);
|
24
24
|
}
|
25
25
|
}
|
@@ -31,7 +31,7 @@ class TransactionalPageOutputDelegate {
|
|
31
31
|
this.delegate = delegate;
|
32
32
|
this.taskQueue = new LinkedBlockingQueue<>();
|
33
33
|
this.executorService = Executors.newSingleThreadExecutor(
|
34
|
-
new ThreadFactoryBuilder().setNameFormat(String.format(THREAD_NAME_FORMAT, source.
|
34
|
+
new ThreadFactoryBuilder().setNameFormat(String.format(THREAD_NAME_FORMAT, source.getTag(), taskIndex)).build()
|
35
35
|
);
|
36
36
|
this.result = executorService.submit(new Worker());
|
37
37
|
}
|
@@ -78,6 +78,10 @@ class TransactionalPageOutputDelegate {
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
+
String getTag() {
|
82
|
+
return source.getTag();
|
83
|
+
}
|
84
|
+
|
81
85
|
private class Worker implements Callable<TaskReport> {
|
82
86
|
@Override
|
83
87
|
public TaskReport call() throws InterruptedException {
|
@@ -24,10 +24,10 @@ import static org.embulk.test.Utils.configFromResource;
|
|
24
24
|
import static org.embulk.test.Utils.record;
|
25
25
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
26
26
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
27
|
-
import static org.junit.jupiter.api.Assertions.assertTrue;
|
28
27
|
|
29
28
|
@EmbulkTest(MultiOutputPlugin.class)
|
30
29
|
class TestMultiOutputPlugin extends EmbulkPluginTest {
|
30
|
+
|
31
31
|
@Test
|
32
32
|
void testMultipleOutputWorking() throws IOException {
|
33
33
|
final ConfigSource inConfig = configFromResource("yaml/in_base.yml");
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-output-multi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shinichi ISHIMURA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ files:
|
|
50
50
|
- LICENSE
|
51
51
|
- README.md
|
52
52
|
- build.gradle
|
53
|
-
- classpath/embulk-output-multi-0.2.
|
53
|
+
- classpath/embulk-output-multi-0.2.2.jar
|
54
54
|
- gradle.properties
|
55
55
|
- gradle/dependency-locks/compileClasspath.lockfile
|
56
56
|
- gradle/dependency-locks/testCompileClasspath.lockfile
|