Skip to content

Commit 2d39685

Browse files
authored
Do not pull layer without title on pull artifact (#582)
2 parents 51ad8fa + ecfb713 commit 2d39685

3 files changed

Lines changed: 65 additions & 4 deletions

File tree

src/main/java/land/oras/Registry.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,16 @@ public void pullArtifact(ContainerRef containerRef, Path path, boolean overwrite
333333
// Only collect layer that are files
334334
String contentType = getContentType(ref);
335335
List<Layer> layers = collectLayers(ref, contentType, false);
336-
if (layers.isEmpty()) {
336+
if (layers.isEmpty()
337+
|| layers.stream().noneMatch(layer -> layer.getAnnotations().containsKey(Const.ANNOTATION_TITLE))) {
337338
LOG.info("Skipped pulling layers without file name in '{}'", Const.ANNOTATION_TITLE);
338339
return;
339340
}
340341
for (Layer layer : layers) {
342+
if (!layer.getAnnotations().containsKey(Const.ANNOTATION_TITLE)) {
343+
LOG.info("Skipped pulling layer without file name in '{}'", Const.ANNOTATION_TITLE);
344+
continue;
345+
}
341346
try (InputStream is = fetchBlob(ref.withDigest(layer.getDigest()))) {
342347
// Unpack or just copy blob
343348
if (Boolean.parseBoolean(layer.getAnnotations().getOrDefault(Const.ANNOTATION_ORAS_UNPACK, "false"))) {
@@ -360,8 +365,7 @@ public void pullArtifact(ContainerRef containerRef, Path path, boolean overwrite
360365
ArchiveUtils.untar(Files.newInputStream(tempArchive.getPath()), path);
361366

362367
} else {
363-
Path targetPath = path.resolve(
364-
layer.getAnnotations().getOrDefault(Const.ANNOTATION_TITLE, layer.getDigest()));
368+
Path targetPath = path.resolve(layer.getAnnotations().get(Const.ANNOTATION_TITLE));
365369
if (Files.exists(targetPath) && !overwrite) {
366370
LOG.info("File already exists: {}", targetPath);
367371
continue;

src/test/java/land/oras/HarborS3ITCase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ void shouldPushJenkinsScriptArtifact() {
205205
ContainerRef containerRef = ContainerRef.parse("demo.goharbor.io/oras/jenkins-cps:latest");
206206
Config config = Config.empty();
207207
Layer layer = Layer.fromData(containerRef, jenkinsfile.getBytes(StandardCharsets.UTF_8))
208-
.withMediaType(contentMediaType);
208+
.withMediaType(contentMediaType)
209+
.withAnnotations(Map.of(Const.ANNOTATION_TITLE, "Jenkinsfile"));
209210
Layer imageLayer = Layer.fromFile(image)
210211
.withMediaType("image/png")
211212
.withAnnotations(Map.of("io.goharbor.artifact.v1alpha1.icon", ""));

src/test/java/land/oras/RegistryTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,62 @@ void shouldPushManifestWithRegistryUrl() {
645645
});
646646
}
647647

648+
@Test
649+
void pullArtifactWithoutLayer() {
650+
Registry registry = Registry.Builder.builder()
651+
.defaults("myuser", "mypass")
652+
.withInsecure(true)
653+
.build();
654+
ContainerRef containerRef1 = ContainerRef.parse("%s/empty-layers".formatted(this.registry.getRegistry()));
655+
Config emptyConfig = Config.empty();
656+
Manifest manifest1 = Manifest.empty().withConfig(emptyConfig);
657+
registry.pushConfig(containerRef1, emptyConfig);
658+
registry.pushManifest(containerRef1, manifest1);
659+
assertDoesNotThrow(() -> {
660+
registry.pullArtifact(containerRef1, artifactDir, true);
661+
});
662+
}
663+
664+
@Test
665+
void pullArtifactShouldPullLayerWithTitleOnly() {
666+
Registry registry = Registry.Builder.builder()
667+
.defaults("myuser", "mypass")
668+
.withInsecure(true)
669+
.build();
670+
ContainerRef containerRef1 = ContainerRef.parse("%s/empty-layers-title".formatted(this.registry.getRegistry()));
671+
Config emptyConfig = Config.empty();
672+
Manifest manifest1 = Manifest.empty().withConfig(emptyConfig);
673+
Layer layer = registry.pushBlob(containerRef1, "hello".getBytes(StandardCharsets.UTF_8))
674+
.withAnnotations(Map.of(Const.ANNOTATION_TITLE, "file.txt"));
675+
Layer layerWithoutTitle = registry.pushBlob(containerRef1, "hello".getBytes(StandardCharsets.UTF_8));
676+
manifest1 = manifest1.withLayers(List.of(layer, layerWithoutTitle));
677+
registry.pushConfig(containerRef1, emptyConfig);
678+
registry.pushManifest(containerRef1, manifest1);
679+
assertDoesNotThrow(() -> {
680+
registry.pullArtifact(containerRef1, artifactDir, true);
681+
});
682+
}
683+
684+
@Test
685+
void pullArtifactShouldPullLayerWithNoTitle() {
686+
Registry registry = Registry.Builder.builder()
687+
.defaults("myuser", "mypass")
688+
.withInsecure(true)
689+
.build();
690+
ContainerRef containerRef1 = ContainerRef.parse("%s/no-layers-title".formatted(this.registry.getRegistry()));
691+
Config emptyConfig = Config.empty();
692+
Manifest manifest1 = Manifest.empty().withConfig(emptyConfig);
693+
Layer layer = registry.pushBlob(containerRef1, "hello".getBytes(StandardCharsets.UTF_8))
694+
.withAnnotations(Map.of());
695+
Layer layerWithoutTitle = registry.pushBlob(containerRef1, "hello".getBytes(StandardCharsets.UTF_8));
696+
manifest1 = manifest1.withLayers(List.of(layer, layerWithoutTitle));
697+
registry.pushConfig(containerRef1, emptyConfig);
698+
registry.pushManifest(containerRef1, manifest1);
699+
assertDoesNotThrow(() -> {
700+
registry.pullArtifact(containerRef1, artifactDir, true);
701+
});
702+
}
703+
648704
@Test
649705
void shouldPushComplexArtifactWithConfigMediaType() throws IOException {
650706
Registry registry = Registry.Builder.builder()

0 commit comments

Comments
 (0)