Skip to content

Commit 91c3656

Browse files
URI-based dependency parsing
1 parent 53353dc commit 91c3656

File tree

3 files changed

+54
-55
lines changed

3 files changed

+54
-55
lines changed

spec/unit/dependency_definition_spec.cr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ module Shards
3535
# bitbucket urls
3636
expect_parses("https://bitbucket.com/foo/bar", "bitbucket", "foo/bar", Any)
3737

38+
# unknown https urls
39+
expect_raises Shards::Error, "Cannot determine resolver for HTTPS URI" do
40+
Shards::DependencyDefinition.parts_from_cli("https://example.com/foo/bar")
41+
end
42+
3843
# Git convenient syntax since resolver matches scheme
3944
expect_parses("git://git.example.org/crystal-library.git", "git", "git://git.example.org/crystal-library.git", Any)
4045
expect_parses("[email protected]:foo/bar.git", "git", "[email protected]:foo/bar.git", Any)
@@ -51,13 +56,19 @@ module Shards
5156
expect_parses("..\\relative\\windows", "path", "../relative/windows", Any)
5257
{% end %}
5358
# Path file schema
54-
expect_parses("file://#{local_relative}", "path", local_relative, Any)
59+
expect_raises Shards::Error, "Invalid file URI" do
60+
Shards::DependencyDefinition.parts_from_cli("file://#{local_relative}")
61+
end
62+
expect_parses("file:#{local_relative}", "path", local_relative, Any)
63+
expect_parses("file:#{local_absolute}", "path", local_absolute, Any)
5564
expect_parses("file://#{local_absolute}", "path", local_absolute, Any)
5665
# Path resolver syntax
5766
expect_parses("path:#{local_absolute}", "path", local_absolute, Any)
5867
expect_parses("path:#{local_relative}", "path", local_relative, Any)
5968
# Other resolvers short
6069
expect_parses("git:git://git.example.org/crystal-library.git", "git", "git://git.example.org/crystal-library.git", Any)
70+
expect_parses("git+https://example.org/foo/bar", "git", "https://example.org/foo/bar", Any)
71+
expect_parses("git:https://example.org/foo/bar", "git", "https://example.org/foo/bar", Any)
6172
end
6273
end
6374
end

src/dependency_definition.cr

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ require "./dependency"
22

33
module Shards
44
class DependencyDefinition
5-
record Parts, resolver_key : String, source : String, requirement : Requirement
5+
record Parts, resolver_key : String, source : String, requirement : Requirement = Any
66

77
property dependency : Dependency
88
# resolver's key and source are normalized. We preserve the key and source to be used
@@ -45,59 +45,51 @@ module Shards
4545
#
4646
# Split to allow better unit testing.
4747
def self.parts_from_cli(value : String) : Parts
48-
resolver_key = nil
49-
source = ""
50-
requirement = Any
51-
52-
if value.starts_with?("file://")
53-
resolver_key = "path"
54-
source = value[7..-1] # drop "file://"
55-
end
56-
57-
# relative paths
58-
path = Path[value].to_posix.to_s
59-
if path.starts_with?("./") || path.starts_with?("../")
60-
resolver_key = "path"
61-
source = path
62-
end
63-
6448
uri = URI.parse(value)
65-
if uri.scheme != "file" && uri.host &&
66-
(resolver_key = GitResolver::KNOWN_PROVIDERS[uri.host]?)
67-
source = uri.path[1..-1].rchop(".git") # drop first "/""
68-
end
69-
70-
if value.starts_with?("git://")
71-
resolver_key = "git"
72-
source = value
73-
end
74-
75-
if value.starts_with?("git@")
76-
resolver_key = "git"
77-
source = value
78-
end
79-
80-
unless resolver_key
81-
Resolver.resolver_keys.each do |key|
82-
key_schema = "#{key}:"
83-
if value.starts_with?(key_schema)
84-
resolver_key = key
85-
source = value.sub(key_schema, "")
86-
87-
# narrow down requirement
88-
if source.includes?("@")
89-
source, version = source.split("@")
90-
requirement = VersionReq.new("~> #{version}")
91-
end
9249

93-
break
50+
case scheme = uri.scheme
51+
when Nil
52+
case value
53+
when .starts_with?("./"), .starts_with?("../")
54+
Parts.new("path", Path[value].to_posix.to_s)
55+
when .starts_with?("git@")
56+
Parts.new("git", value)
57+
else
58+
raise Shards::Error.new("Invalid dependency format: #{value}")
59+
end
60+
when "file"
61+
raise Shards::Error.new("Invalid file URI: #{uri}") if !uri.host.in?(nil, "", "localhost") || uri.port || uri.user
62+
Parts.new("path", uri.path)
63+
when "https"
64+
if resolver_key = GitResolver::KNOWN_PROVIDERS[uri.host]?
65+
Parts.new(resolver_key, uri.path[1..-1].rchop(".git")) # drop first "/""
66+
else
67+
raise Shards::Error.new("Cannot determine resolver for HTTPS URI: #{value}")
68+
end
69+
when "git"
70+
if uri.host
71+
Parts.new("git", uri.to_s)
72+
else
73+
Parts.new("git", uri.path)
74+
end
75+
when "git+https"
76+
uri.scheme = "https"
77+
Parts.new("git", uri.to_s)
78+
else
79+
if resolver_class = Resolver::RESOLVER_CLASSES[scheme]?
80+
uri.scheme = nil
81+
source = uri.to_s
82+
# narrow down requirement
83+
requirement = Any
84+
if source.includes?("@")
85+
source, version = source.split("@")
86+
requirement = VersionReq.new("~> #{version}")
9487
end
88+
89+
return Parts.new(scheme, source, requirement)
9590
end
91+
raise Shards::Error.new("Invalid dependency format: #{value}")
9692
end
97-
98-
raise Shards::Error.new("Invalid dependency format: #{value}") unless resolver_key
99-
100-
Parts.new(resolver_key: resolver_key, source: source, requirement: requirement)
10193
end
10294
end
10395
end

src/resolvers/resolver.cr

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,9 @@ module Shards
100100
end
101101

102102
private record ResolverCacheKey, key : String, name : String, source : String
103-
private RESOLVER_CLASSES = {} of String => Resolver.class
103+
RESOLVER_CLASSES = {} of String => Resolver.class
104104
private RESOLVER_CACHE = {} of ResolverCacheKey => Resolver
105105

106-
def self.resolver_keys
107-
RESOLVER_CLASSES.keys
108-
end
109-
110106
def self.register_resolver(key, resolver)
111107
RESOLVER_CLASSES[key] = resolver
112108
end

0 commit comments

Comments
 (0)