Skip to content

Commit

Permalink
Make Git::URL.clone_to handle cloning to bare and mirror repos
Browse files Browse the repository at this point in the history
Signed-off-by: James Couball <jcouball@yahoo.com>
  • Loading branch information
jcouball committed Apr 24, 2022
1 parent 13471d7 commit cf8d1a7
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 148 deletions.
13 changes: 9 additions & 4 deletions lib/git/url.rb
Expand Up @@ -52,7 +52,7 @@ def self.parse(url)
end
end

# The name `git clone` would use for the repository directory for the given URL
# The directory `git clone` would use for the repository directory for the given URL
#
# @example
# Git::URL.clone_to('https://github.com/ruby-git/ruby-git.git') #=> 'ruby-git'
Expand All @@ -61,12 +61,17 @@ def self.parse(url)
#
# @return [String] the name of the repository directory
#
def self.clone_to(url)
def self.clone_to(url, bare: false, mirror: false)
uri = parse(url)
path_parts = uri.path.split('/')
path_parts.pop if path_parts.last == '.git'

path_parts.last.sub(/\.git$/, '')
directory = path_parts.last
if bare || mirror
directory += '.git' unless directory.end_with?('.git')
elsif directory.end_with?('.git')
directory = directory[0..-5]
end
directory
end
end

Expand Down
144 changes: 0 additions & 144 deletions tests/units/test_url.rb

This file was deleted.

62 changes: 62 additions & 0 deletions tests/units/test_url_clone_to.rb
@@ -0,0 +1,62 @@
# frozen_string_literal: true

require 'test/unit'

# Tests Git::URL.clone_to
#
class TestURLCloneTo < Test::Unit::TestCase
def test_clone_to_full_repo
GIT_URLS.each do |url_data|
url = url_data[:url]
expected_path = url_data[:expected_path]
actual_path = Git::URL.clone_to(url)
assert_equal(
expected_path, actual_path,
"Failed to determine the clone path for URL '#{url}' correctly"
)
end
end

def test_clone_to_bare_repo
GIT_URLS.each do |url_data|
url = url_data[:url]
expected_path = url_data[:expected_bare_path]
actual_path = Git::URL.clone_to(url, bare: true)
assert_equal(
expected_path, actual_path,
"Failed to determine the clone path for URL '#{url}' correctly"
)
end
end

def test_clone_to_mirror_repo
GIT_URLS.each do |url_data|
url = url_data[:url]
# The expected_path is the same for bare and mirror repos
expected_path = url_data[:expected_bare_path]
actual_path = Git::URL.clone_to(url, mirror: true)
assert_equal(
expected_path, actual_path,
"Failed to determine the clone path for URL '#{url}' correctly"
)
end
end

GIT_URLS = [
{
url: 'https://github.com/org/repo',
expected_path: 'repo',
expected_bare_path: 'repo.git'
},
{
url: 'https://github.com/org/repo.git',
expected_path: 'repo',
expected_bare_path: 'repo.git'
},
{
url: 'https://git.mydomain.com/org/repo/.git',
expected_path: 'repo',
expected_bare_path: 'repo.git'
}
].freeze
end
100 changes: 100 additions & 0 deletions tests/units/test_url_parse.rb
@@ -0,0 +1,100 @@
# frozen_string_literal: true

require 'test/unit'

# Tests Git::URL.parse
#
class TestURLParse < Test::Unit::TestCase
def test_parse_with_invalid_url
url = 'user@host.xz:/path/to/repo.git/'
assert_raise(Addressable::URI::InvalidURIError) do
Git::URL.parse(url)
end
end

def test_parse
GIT_URLS.each do |url_data|
url = url_data[:url]
expected_uri = url_data[:expected_uri]
actual_uri = Git::URL.parse(url).to_hash.delete_if { |_key, value| value.nil? }
assert_equal(expected_uri, actual_uri, "Failed to parse URL '#{url}' correctly")
end
end

# For any URL, #to_s should return the url passed to Git::URL.parse(url)
def test_to_s
GIT_URLS.each do |url_data|
url = url_data[:url]
to_s = Git::URL.parse(url).to_s
assert_equal(url, to_s, "Parsed URI#to_s does not return the original URL '#{url}' correctly")
end
end

GIT_URLS = [
{
url: 'ssh://host.xz/path/to/repo.git/',
expected_uri: { scheme: 'ssh', host: 'host.xz', path: '/path/to/repo.git/' }
},
{
url: 'ssh://host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'ssh', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'ssh:///path/to/repo.git/',
expected_uri: { scheme: 'ssh', host: '', path: '/path/to/repo.git/' }
},
{
url: 'user@host.xz:path/to/repo.git/',
expected_uri: { scheme: 'git-alt', user: 'user', host: 'host.xz', path: '/path/to/repo.git/' }
},
{
url: 'host.xz:path/to/repo.git/',
expected_uri: { scheme: 'git-alt', host: 'host.xz', path: '/path/to/repo.git/' }
},
{
url: 'git://host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'git', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'git://user@host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'git', user: 'user', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'https://host.xz/path/to/repo.git/',
expected_uri: { scheme: 'https', host: 'host.xz', path: '/path/to/repo.git/' }
},
{
url: 'https://host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'https', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'ftps://host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'ftps', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'ftps://host.xz:4443/path/to/repo.git/',
expected_uri: { scheme: 'ftps', host: 'host.xz', port: 4443, path: '/path/to/repo.git/' }
},
{
url: 'file:./relative-path/to/repo.git/',
expected_uri: { scheme: 'file', path: './relative-path/to/repo.git/' }
},
{
url: 'file:///path/to/repo.git/',
expected_uri: { scheme: 'file', host: '', path: '/path/to/repo.git/' }
},
{
url: 'file:///path/to/repo.git',
expected_uri: { scheme: 'file', host: '', path: '/path/to/repo.git' }
},
{
url: 'file://host.xz/path/to/repo.git',
expected_uri: { scheme: 'file', host: 'host.xz', path: '/path/to/repo.git' }
},
{ url: '/path/to/repo.git/', expected_uri: { path: '/path/to/repo.git/' } },
{ url: '/path/to/bare-repo/.git', expected_uri: { path: '/path/to/bare-repo/.git' } },
{ url: 'relative-path/to/repo.git/', expected_uri: { path: 'relative-path/to/repo.git/' } },
{ url: './relative-path/to/repo.git/', expected_uri: { path: './relative-path/to/repo.git/' } },
{ url: '../ruby-git/.git', expected_uri: { path: '../ruby-git/.git' } }
].freeze
end

0 comments on commit cf8d1a7

Please sign in to comment.