diff --git a/tests/pkg/assets/install5/gold/test.gold b/tests/pkg/assets/install5/gold/test.gold new file mode 100644 index 000000000..0896c98b5 --- /dev/null +++ b/tests/pkg/assets/install5/gold/test.gold @@ -0,0 +1,75 @@ +OK +[pkg, init] +================== +OK +[pkg, registry, add, --local, test-reg2, registry-ambiguous] +================== +// Ambiguous pkg1 +================== +Aborted +[pkg, install, pkg1] +Error: Multiple packages found for 'pkg1' in all registries. +================== +// Disambiguate by giving full URL. +================== +OK +[pkg, install, localhost:<[*PORT*]>/pkg/pkg1] +Package 'pkg1@1.0.0' installed with prefix 'pkg1'. +================== +// Ambiguous pkg2 +================== +OK +[pkg, search, --verbose, pkg2] +pkg2: + description: Ambiguous to pkg2. Prefixes URL. This is an invalid URL for testing. + url: example.com/localhost:<[*PORT*]>/pkg/pkg2 + version: 1.0.0 + hash: <[*HASH*]> + +pkg2: + description: git-package 2 + url: localhost:<[*PORT*]>/pkg/pkg2 + version: 2.4.2 + hash: <[*HASH*]> + +================== +// Disambiguate by giving full URL even though that's the suffix of the longer one. +================== +OK +[pkg, install, localhost:<[*PORT*]>/pkg/pkg2] +Package 'pkg2@2.4.2' installed with prefix 'pkg2'. +================== +// Ambiguous 'ambiguous' +================== +OK +[pkg, search, --verbose, ambiguous] +ambiguous: + description: first of two packages that have long name that is equal + url: localhost:<[*PORT*]>/a/b/c/d/ambiguous + version: 3.1.2 + hash: <[*HASH*]> + +ambiguous: + description: second of two packages that have long name that is equal + url: localhost:<[*PORT*]>/a2/b/c/d/ambiguous + version: 3.1.2 + hash: <[*HASH*]> + +pkg2: + description: Ambiguous to pkg2. Prefixes URL. This is an invalid URL for testing. + url: example.com/localhost:<[*PORT*]>/pkg/pkg2 + version: 1.0.0 + hash: <[*HASH*]> + +================== +// Need to add more segments to disambiguate. +================== +Aborted +[pkg, install, b/c/d/ambiguous] +Error: Multiple packages found for 'b/c/d/ambiguous' in all registries. +================== +// Will still yield an error (because we don't have the package), +================== +Aborted +[pkg, install, a/b/c/d/ambiguous] +Error: Failed to download package 'localhost:<[*PORT*]>/a/b/c/d/ambiguous@3.1.2': Invalid repository http://localhost:<[*PORT*]>/a/b/c/d/ambiguous, Not Found diff --git a/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous1/3.1.2/desc.yaml b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous1/3.1.2/desc.yaml new file mode 100644 index 000000000..30b621bc5 --- /dev/null +++ b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous1/3.1.2/desc.yaml @@ -0,0 +1,5 @@ +name: ambiguous +description: first of two packages that have long name that is equal +url: localhost:<[*PORT*]>/a/b/c/d/ambiguous +version: 3.1.2 +hash: deadbeef1234567890abcdef1234567890abcdef diff --git a/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous2/3.1.2/desc.yaml b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous2/3.1.2/desc.yaml new file mode 100644 index 000000000..4f61c703f --- /dev/null +++ b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/ambiguous2/3.1.2/desc.yaml @@ -0,0 +1,5 @@ +name: ambiguous +description: second of two packages that have long name that is equal +url: localhost:<[*PORT*]>/a2/b/c/d/ambiguous +version: 3.1.2 +hash: deadbeef1234567890abcdef1234567890abcdef diff --git a/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg1/1.0.0/desc.yaml b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg1/1.0.0/desc.yaml new file mode 100644 index 000000000..3e7df062b --- /dev/null +++ b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg1/1.0.0/desc.yaml @@ -0,0 +1,5 @@ +name: pkg1 +description: same name as pkg1 from shared registry +url: example.com/pkg1 +version: 1.0.0 +hash: 9876543210 diff --git a/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg2/1.0.0/desc.yaml b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg2/1.0.0/desc.yaml new file mode 100644 index 000000000..5c1c5963d --- /dev/null +++ b/tests/pkg/assets/install5/registry-ambiguous/GIT_TAGS/1.0.0/pkg2/1.0.0/desc.yaml @@ -0,0 +1,5 @@ +name: pkg2 +description: Ambiguous to pkg2. Prefixes URL. This is an invalid URL for testing. +url: example.com/localhost:<[*PORT*]>/pkg/pkg2 +version: 1.0.0 +hash: 3141592653 diff --git a/tests/pkg/assets/install5/registry-ambiguous/README.txt b/tests/pkg/assets/install5/registry-ambiguous/README.txt new file mode 100644 index 000000000..81eb4e728 --- /dev/null +++ b/tests/pkg/assets/install5/registry-ambiguous/README.txt @@ -0,0 +1,2 @@ +The tag number of the registry isn't important as Toit-package always just +pulls the default branch. diff --git a/tests/pkg/assets/install5/test.toit b/tests/pkg/assets/install5/test.toit new file mode 100644 index 000000000..639920025 --- /dev/null +++ b/tests/pkg/assets/install5/test.toit @@ -0,0 +1,8 @@ +// Copyright (C) 2025 Toit contributors. +// Use of this source code is governed by a Zero-Clause BSD license that can +// be found in the tests/LICENSE file. + +import pkg1 + +main: + print pkg1.identify diff --git a/tests/pkg/gold-tester.toit b/tests/pkg/gold-tester.toit index 345c5511c..eca147cf0 100644 --- a/tests/pkg/gold-tester.toit +++ b/tests/pkg/gold-tester.toit @@ -82,6 +82,9 @@ class GoldTester: working-dir -> string: return working-dir_ + port -> int: + return port_ + package-cache-path pkg-suffix/string --version/string -> string: bytes := file.read-contents "$working-dir_/.packages/contents.json" packages := json.decode bytes diff --git a/tests/pkg/install5-gold-test.toit b/tests/pkg/install5-gold-test.toit new file mode 100644 index 000000000..4651b7db7 --- /dev/null +++ b/tests/pkg/install5-gold-test.toit @@ -0,0 +1,31 @@ +// Copyright (C) 2025 Toit contributors. +// Use of this source code is governed by a Zero-Clause BSD license that can +// be found in the tests/LICENSE file. + +import host.file + +import .gold-tester + +main args: + with-gold-tester args --with-git-pkg-registry: test it + +test tester/GoldTester: + tester.gold "test" [ + ["pkg", "init"], // So we don't accidentally use a /tmp/package.yaml. + ["pkg", "registry", "add", "--local", "test-reg2", "registry-ambiguous"], + ["// Ambiguous pkg1"], + ["pkg", "install", "pkg1"], + ["// Disambiguate by giving full URL."], + ["pkg", "install", "localhost:$tester.port/pkg/pkg1"], + ["// Ambiguous pkg2"], + ["pkg", "search", "--verbose", "pkg2"], + ["// Disambiguate by giving full URL even though that's the suffix of the longer one."], + ["pkg", "install", "localhost:$tester.port/pkg/pkg2"], + ["// Ambiguous 'ambiguous'"], + ["pkg", "search", "--verbose", "ambiguous"], + ["// Need to add more segments to disambiguate."], + ["pkg", "install", "b/c/d/ambiguous"], + ["// Will still yield an error (because we don't have the package),", + "// but it's a different one"], + ["pkg", "install", "a/b/c/d/ambiguous"] + ] diff --git a/tools/pkg/commands/search.toit b/tools/pkg/commands/search.toit index 4bc7c32c8..9aa1f43c4 100644 --- a/tools/pkg/commands/search.toit +++ b/tools/pkg/commands/search.toit @@ -37,6 +37,10 @@ class SearchCommand extends PkgCommand: execute: registries.sync search-result := registries.search --free-text search-string + search-result = search-result.sort: | a/Description b/Description | + a.name.compare-to b.name --if-equal=: + a.url.compare-to b.url --if-equal=: + a.version.compare-to b.version url-to-description/Map := {:} search-result.do: | description/Description | diff --git a/tools/pkg/project/project.toit b/tools/pkg/project/project.toit index 313c3e955..9c76d667c 100644 --- a/tools/pkg/project/project.toit +++ b/tools/pkg/project/project.toit @@ -220,6 +220,16 @@ class Project: ensure-downloaded url/string version/SemanticVersion -> Map --cached-contents/Map?=null --hash/string: + e := catch: + return ensure-downloaded_ url version + --cached-contents=cached-contents + --hash=hash + ui_.abort "Failed to download package '$url@$version': $e" + unreachable + + ensure-downloaded_ url/string version/SemanticVersion -> Map + --cached-contents/Map? + --hash/string: if not cached-contents: cached-contents = cached-repository-contents_ version-string := version.to-string if cached-contents.contains url and diff --git a/tools/pkg/registry/registry.toit b/tools/pkg/registry/registry.toit index c204a1ffb..309d93494 100644 --- a/tools/pkg/registry/registry.toit +++ b/tools/pkg/registry/registry.toit @@ -97,6 +97,11 @@ class Registries: if urls.size == 1: return search-results[0][1] + // If there is a full match, return that. + search-results.do: + if it[1].url == search-string: + return it[1] + registry-info := registry-name != null ? "in registry $registry-name." : "in all registries." ui_.abort "Multiple packages found for '$search-string' $registry-info"