Fix parsing of dependency notation URIs (#1570)

Fixes a thrown exception when path segments contain characters that
aren't URI safe (e.g. `import "@foo/bar baz.pkl"`).

Closes #1545
This commit is contained in:
Daniel Chao
2026-05-07 13:00:52 -07:00
committed by GitHub
parent 8ff03cfac0
commit 38733e5781
11 changed files with 66 additions and 4 deletions
@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,10 @@
package org.pkl.core.packages;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.Objects;
import org.pkl.core.PklBugException;
import org.pkl.core.Version;
import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable;
@@ -53,7 +55,15 @@ public abstract class Dependency {
public URI resolveAssetUri(URI projectBaseUri, PackageAssetUri packageAssetUri) {
// drop 1 to remove leading `/`
var assetPath = packageAssetUri.getAssetPath().substring(1);
return projectBaseUri.resolve(IoUtils.toNormalizedPathString(path.resolve(assetPath)));
var resolvedPath = path.resolve(assetPath);
var normalized = IoUtils.toNormalizedPathString(resolvedPath);
try {
var relativeUri = new URI(null, null, normalized, null);
return projectBaseUri.resolve(relativeUri);
} catch (URISyntaxException e) {
// impossible; we started from valid URIs to begin with.
throw PklBugException.unreachableCode();
}
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.pkl.core.packages;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import org.pkl.core.PklBugException;
import org.pkl.core.Version;
import org.pkl.core.util.ErrorMessages;
import org.pkl.core.util.IoUtils;
@@ -40,7 +41,13 @@ public final class PackageAssetUri {
}
public PackageAssetUri(PackageUri packageUri, String assetPath) {
this.uri = packageUri.getUri().resolve("#" + assetPath);
var base = packageUri.getUri();
try {
this.uri = new URI(base.getScheme(), base.getSchemeSpecificPart(), assetPath);
} catch (URISyntaxException e) {
// impossible condition, we have a valid URI to start with.
throw PklBugException.unreachableCode();
}
this.packageUri = packageUri;
this.assetPath = assetPath;
}
@@ -0,0 +1,8 @@
amends "pkl:Project"
package {
name = "packageWithSpaces"
baseUri = "package://localhost:0/packageWithSpaces"
version = "1.0.0"
packageZipUrl = "https://localhost:0/packageWithSpaces/packageWithSpaces-\(version).zip"
}
@@ -0,0 +1,8 @@
amends "pkl:Project"
dependencies {
["birds"] {
uri = "package://localhost:0/birds@0.7.0"
}
["packageWithSpaces"] = import("../packageWithSpaces/PklProject")
}
@@ -0,0 +1,17 @@
{
"schemaVersion": 1,
"resolvedDependencies": {
"package://localhost:0/birds@0": {
"type": "remote",
"uri": "projectpackage://localhost:0/birds@0.7.0",
"checksums": {
"sha256": "$skipChecksumVerification"
}
},
"package://localhost:0/packageWithSpaces@1": {
"type": "local",
"uri": "projectpackage://localhost:0/packageWithSpaces@1.0.0",
"path": "../packageWithSpaces/"
}
}
}
@@ -0,0 +1,3 @@
import* "@birds/catalog/{Ostrich,Swallow}.pkl" as myCatalog
res = myCatalog.keys
@@ -0,0 +1,3 @@
import "@packageWithSpaces/module with spaces.pkl" as mod
res = mod
@@ -0,0 +1 @@
res = Set("@birds/catalog/Ostrich.pkl", "@birds/catalog/Swallow.pkl")
@@ -0,0 +1,3 @@
res {
foo = 1
}