20
20
21
21
import build .bazel .remote .execution .v2 .DigestFunction ;
22
22
import com .google .devtools .build .lib .actions .Action ;
23
+ import com .google .devtools .build .lib .actions .Artifact ;
24
+ import com .google .devtools .build .lib .actions .Artifact .SpecialArtifact ;
23
25
import com .google .devtools .build .lib .actions .EnvironmentalExecException ;
24
26
import com .google .devtools .build .lib .actions .ExecException ;
25
27
import com .google .devtools .build .lib .actions .cache .OutputMetadataStore ;
26
28
import com .google .devtools .build .lib .events .EventHandler ;
27
29
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .CleanRequest ;
28
30
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .CleanResponse ;
31
+ import com .google .devtools .build .lib .remote .BazelOutputServiceProto .FinalizeArtifactsRequest ;
32
+ import com .google .devtools .build .lib .remote .BazelOutputServiceProto .FinalizeArtifactsResponse ;
29
33
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .FinalizeBuildRequest ;
30
34
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .FinalizeBuildResponse ;
31
35
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .StageArtifactsRequest ;
32
- import com .google .devtools .build .lib .remote .BazelOutputServiceProto .StageArtifactsRequest .Artifact ;
33
36
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .StageArtifactsResponse ;
34
37
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .StartBuildRequest ;
35
38
import com .google .devtools .build .lib .remote .BazelOutputServiceProto .StartBuildResponse ;
64
67
public class BazelOutputService implements OutputService {
65
68
66
69
private final String outputBaseId ;
70
+ private final Supplier <Path > execRootSupplier ;
67
71
private final Supplier <Path > outputPathSupplier ;
68
72
private final DigestFunction .Value digestFunction ;
69
73
private final RemoteOptions remoteOptions ;
@@ -75,13 +79,15 @@ public class BazelOutputService implements OutputService {
75
79
76
80
public BazelOutputService (
77
81
Path outputBase ,
82
+ Supplier <Path > execRootSupplier ,
78
83
Supplier <Path > outputPathSupplier ,
79
84
DigestFunction .Value digestFunction ,
80
85
RemoteOptions remoteOptions ,
81
86
boolean verboseFailures ,
82
87
RemoteRetrier retrier ,
83
88
ReferenceCountedChannel channel ) {
84
89
this .outputBaseId = DigestUtil .hashCodeToString (md5 ().hashString (outputBase .toString (), UTF_8 ));
90
+ this .execRootSupplier = execRootSupplier ;
85
91
this .outputPathSupplier = outputPathSupplier ;
86
92
this .digestFunction = digestFunction ;
87
93
this .remoteOptions = remoteOptions ;
@@ -247,7 +253,7 @@ protected void stageArtifacts(List<FileMetadata> files) throws IOException, Inte
247
253
request .setBuildId (buildId );
248
254
for (var file : files ) {
249
255
request .addArtifacts (
250
- Artifact .newBuilder ()
256
+ StageArtifactsRequest . Artifact .newBuilder ()
251
257
.setPath (file .path ().relativeTo (outputPath ).toString ())
252
258
.setLocator (
253
259
Any .pack (FileArtifactLocator .newBuilder ().setDigest (file .digest ()).build ()))
@@ -328,7 +334,63 @@ private FinalizeBuildResponse finalizeBuild(FinalizeBuildRequest request)
328
334
@ Override
329
335
public void finalizeAction (Action action , OutputMetadataStore outputMetadataStore )
330
336
throws IOException , EnvironmentalExecException , InterruptedException {
331
- // TODO(chiwang): implement this
337
+ var execRoot = execRootSupplier .get ();
338
+ var outputPath = outputPathSupplier .get ();
339
+
340
+ var request = FinalizeArtifactsRequest .newBuilder ();
341
+ request .setBuildId (buildId );
342
+ for (var output : action .getOutputs ()) {
343
+ if (outputMetadataStore .artifactOmitted (output )) {
344
+ continue ;
345
+ }
346
+
347
+ if (output .isTreeArtifact ()) {
348
+ // TODO(chiwang): Use TreeArtifactLocator
349
+ var children = outputMetadataStore .getTreeArtifactChildren ((SpecialArtifact ) output );
350
+ for (var child : children ) {
351
+ addArtifact (outputMetadataStore , execRoot , outputPath , request , child );
352
+ }
353
+ } else {
354
+ addArtifact (outputMetadataStore , execRoot , outputPath , request , output );
355
+ }
356
+ }
357
+
358
+ var unused = finalizeArtifacts (request .build ());
359
+ }
360
+
361
+ private FinalizeArtifactsResponse finalizeArtifacts (FinalizeArtifactsRequest request )
362
+ throws IOException , InterruptedException {
363
+ return retrier .execute (
364
+ () ->
365
+ channel .withChannelBlocking (
366
+ channel -> {
367
+ try {
368
+ return BazelOutputServiceGrpc .newBlockingStub (channel )
369
+ .finalizeArtifacts (request );
370
+ } catch (StatusRuntimeException e ) {
371
+ throw new IOException (e );
372
+ }
373
+ }));
374
+ }
375
+
376
+ private void addArtifact (
377
+ OutputMetadataStore outputMetadataStore ,
378
+ Path execRoot ,
379
+ Path outputPath ,
380
+ FinalizeArtifactsRequest .Builder builder ,
381
+ Artifact output )
382
+ throws IOException , InterruptedException {
383
+ checkState (!output .isTreeArtifact ());
384
+ var metadata = outputMetadataStore .getOutputMetadata (output );
385
+ if (metadata .getType ().isFile ()) {
386
+ var digest = DigestUtil .buildDigest (metadata .getDigest (), metadata .getSize ());
387
+ var path = execRoot .getRelative (output .getExecPath ()).relativeTo (outputPath ).toString ();
388
+ builder .addArtifacts (
389
+ FinalizeArtifactsRequest .Artifact .newBuilder ()
390
+ .setPath (path )
391
+ .setLocator (Any .pack (FileArtifactLocator .newBuilder ().setDigest (digest ).build ()))
392
+ .build ());
393
+ }
332
394
}
333
395
334
396
@ Override
0 commit comments