Skip to content

Commit cf8d1a7

Browse files
committed
Make Git::URL.clone_to handle cloning to bare and mirror repos
Signed-off-by: James Couball <jcouball@yahoo.com>
1 parent 13471d7 commit cf8d1a7

File tree

4 files changed

+171
-148
lines changed

4 files changed

+171
-148
lines changed

lib/git/url.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def self.parse(url)
5252
end
5353
end
5454

55-
# The name `git clone` would use for the repository directory for the given URL
55+
# The directory `git clone` would use for the repository directory for the given URL
5656
#
5757
# @example
5858
# Git::URL.clone_to('https://github.com/ruby-git/ruby-git.git') #=> 'ruby-git'
@@ -61,12 +61,17 @@ def self.parse(url)
6161
#
6262
# @return [String] the name of the repository directory
6363
#
64-
def self.clone_to(url)
64+
def self.clone_to(url, bare: false, mirror: false)
6565
uri = parse(url)
6666
path_parts = uri.path.split('/')
6767
path_parts.pop if path_parts.last == '.git'
68-
69-
path_parts.last.sub(/\.git$/, '')
68+
directory = path_parts.last
69+
if bare || mirror
70+
directory += '.git' unless directory.end_with?('.git')
71+
elsif directory.end_with?('.git')
72+
directory = directory[0..-5]
73+
end
74+
directory
7075
end
7176
end
7277

tests/units/test_url.rb

Lines changed: 0 additions & 144 deletions
This file was deleted.

tests/units/test_url_clone_to.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
require 'test/unit'
4+
5+
# Tests Git::URL.clone_to
6+
#
7+
class TestURLCloneTo < Test::Unit::TestCase
8+
def test_clone_to_full_repo
9+
GIT_URLS.each do |url_data|
10+
url = url_data[:url]
11+
expected_path = url_data[:expected_path]
12+
actual_path = Git::URL.clone_to(url)
13+
assert_equal(
14+
expected_path, actual_path,
15+
"Failed to determine the clone path for URL '#{url}' correctly"
16+
)
17+
end
18+
end
19+
20+
def test_clone_to_bare_repo
21+
GIT_URLS.each do |url_data|
22+
url = url_data[:url]
23+
expected_path = url_data[:expected_bare_path]
24+
actual_path = Git::URL.clone_to(url, bare: true)
25+
assert_equal(
26+
expected_path, actual_path,
27+
"Failed to determine the clone path for URL '#{url}' correctly"
28+
)
29+
end
30+
end
31+
32+
def test_clone_to_mirror_repo
33+
GIT_URLS.each do |url_data|
34+
url = url_data[:url]
35+
# The expected_path is the same for bare and mirror repos
36+
expected_path = url_data[:expected_bare_path]
37+
actual_path = Git::URL.clone_to(url, mirror: true)
38+
assert_equal(
39+
expected_path, actual_path,
40+
"Failed to determine the clone path for URL '#{url}' correctly"
41+
)
42+
end
43+
end
44+
45+
GIT_URLS = [
46+
{
47+
url: 'https://github.com/org/repo',
48+
expected_path: 'repo',
49+
expected_bare_path: 'repo.git'
50+
},
51+
{
52+
url: 'https://github.com/org/repo.git',
53+
expected_path: 'repo',
54+
expected_bare_path: 'repo.git'
55+
},
56+
{
57+
url: 'https://git.mydomain.com/org/repo/.git',
58+
expected_path: 'repo',
59+
expected_bare_path: 'repo.git'
60+
}
61+
].freeze
62+
end

tests/units/test_url_parse.rb

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# frozen_string_literal: true
2+
3+
require 'test/unit'
4+
5+
# Tests Git::URL.parse
6+
#
7+
class TestURLParse < Test::Unit::TestCase
8+
def test_parse_with_invalid_url
9+
url = 'user@host.xz:/path/to/repo.git/'
10+
assert_raise(Addressable::URI::InvalidURIError) do
11+
Git::URL.parse(url)
12+
end
13+
end
14+
15+
def test_parse
16+
GIT_URLS.each do |url_data|
17+
url = url_data[:url]
18+
expected_uri = url_data[:expected_uri]
19+
actual_uri = Git::URL.parse(url).to_hash.delete_if { |_key, value| value.nil? }
20+
assert_equal(expected_uri, actual_uri, "Failed to parse URL '#{url}' correctly")
21+
end
22+
end
23+
24+
# For any URL, #to_s should return the url passed to Git::URL.parse(url)
25+
def test_to_s
26+
GIT_URLS.each do |url_data|
27+
url = url_data[:url]
28+
to_s = Git::URL.parse(url).to_s
29+
assert_equal(url, to_s, "Parsed URI#to_s does not return the original URL '#{url}' correctly")
30+
end
31+
end
32+
33+
GIT_URLS = [
34+
{
35+
url: 'ssh://host.xz/path/to/repo.git/',
36+
expected_uri: { scheme: 'ssh', host: 'host.xz', path: '/path/to/repo.git/' }
37+
},
38+
{
39+
url: 'ssh://host.xz:4443/path/to/repo.git/',
40+
expected_uri: { scheme: 'ssh', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
41+
},
42+
{
43+
url: 'ssh:///path/to/repo.git/',
44+
expected_uri: { scheme: 'ssh', host: '', path: '/path/to/repo.git/' }
45+
},
46+
{
47+
url: 'user@host.xz:path/to/repo.git/',
48+
expected_uri: { scheme: 'git-alt', user: 'user', host: 'host.xz', path: '/path/to/repo.git/' }
49+
},
50+
{
51+
url: 'host.xz:path/to/repo.git/',
52+
expected_uri: { scheme: 'git-alt', host: 'host.xz', path: '/path/to/repo.git/' }
53+
},
54+
{
55+
url: 'git://host.xz:4443/path/to/repo.git/',
56+
expected_uri: { scheme: 'git', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
57+
},
58+
{
59+
url: 'git://user@host.xz:4443/path/to/repo.git/',
60+
expected_uri: { scheme: 'git', user: 'user', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
61+
},
62+
{
63+
url: 'https://host.xz/path/to/repo.git/',
64+
expected_uri: { scheme: 'https', host: 'host.xz', path: '/path/to/repo.git/' }
65+
},
66+
{
67+
url: 'https://host.xz:4443/path/to/repo.git/',
68+
expected_uri: { scheme: 'https', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
69+
},
70+
{
71+
url: 'ftps://host.xz:4443/path/to/repo.git/',
72+
expected_uri: { scheme: 'ftps', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
73+
},
74+
{
75+
url: 'ftps://host.xz:4443/path/to/repo.git/',
76+
expected_uri: { scheme: 'ftps', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
77+
},
78+
{
79+
url: 'file:./relative-path/to/repo.git/',
80+
expected_uri: { scheme: 'file', path: './relative-path/to/repo.git/' }
81+
},
82+
{
83+
url: 'file:///path/to/repo.git/',
84+
expected_uri: { scheme: 'file', host: '', path: '/path/to/repo.git/' }
85+
},
86+
{
87+
url: 'file:///path/to/repo.git',
88+
expected_uri: { scheme: 'file', host: '', path: '/path/to/repo.git' }
89+
},
90+
{
91+
url: 'file://host.xz/path/to/repo.git',
92+
expected_uri: { scheme: 'file', host: 'host.xz', path: '/path/to/repo.git' }
93+
},
94+
{ url: '/path/to/repo.git/', expected_uri: { path: '/path/to/repo.git/' } },
95+
{ url: '/path/to/bare-repo/.git', expected_uri: { path: '/path/to/bare-repo/.git' } },
96+
{ url: 'relative-path/to/repo.git/', expected_uri: { path: 'relative-path/to/repo.git/' } },
97+
{ url: './relative-path/to/repo.git/', expected_uri: { path: './relative-path/to/repo.git/' } },
98+
{ url: '../ruby-git/.git', expected_uri: { path: '../ruby-git/.git' } }
99+
].freeze
100+
end

0 commit comments

Comments
 (0)