Skip to content

Commit 45b467c

Browse files
authored
Make the directory param to Git.clone optional (#578)
Signed-off-by: James Couball <jcouball@yahoo.com>
1 parent b92130c commit 45b467c

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,23 @@ g = Git.init
204204
{ :repository => '/opt/git/proj.git',
205205
:index => '/tmp/index'} )
206206

207-
g = Git.clone(URI, NAME, :path => '/tmp/checkout')
207+
# Clone from a git url
208+
git_url = 'https://github.com/ruby-git/ruby-git.git'
209+
# Clone into the ruby-git directory
210+
g = Git.clone(git_url)
211+
212+
# Clone into /tmp/clone/ruby-git-clean
213+
name = 'ruby-git-clean'
214+
path = '/tmp/clone'
215+
g = Git.clone(git_url, name, :path => path)
216+
g.dir #=> /tmp/clone/ruby-git-clean
217+
208218
g.config('user.name', 'Scott Chacon')
209219
g.config('user.email', 'email@email.com')
210220

211221
# Clone can take an optional logger
212222
logger = Logger.new
213-
g = Git.clone(URI, NAME, :log => logger)
223+
g = Git.clone(git_url, NAME, :log => logger)
214224

215225
g.add # git add -- "."
216226
g.add(:all=>true) # git add --all -- "."

lib/git.rb

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,23 @@ def self.bare(git_dir, options = {})
107107
# @see https://git-scm.com/docs/git-clone git clone
108108
# @see https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a GIT URLs
109109
#
110-
# @param [URI, Pathname] repository The (possibly remote) repository to clone
110+
# @param repository_url [URI, Pathname] The (possibly remote) repository url to clone
111111
# from. See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a)
112112
# for more information.
113113
#
114-
# @param [Pathname] name The directory to clone into.
114+
# @param directory [Pathname, nil] The directory to clone into
115+
#
116+
# If `directory` is a relative directory it is relative to the `path` option if
117+
# given. If `path` is not given, `directory` is relative to the current working
118+
# directory.
119+
#
120+
# If `nil`, `directory` will be set to the basename of the last component of
121+
# the path from the `repository_url`. For example, for the URL:
122+
# `https://github.com/org/repo.git`, `directory` will be set to `repo`.
123+
#
124+
# If the last component of the path is `.git`, the next-to-last component of
125+
# the path is used. For example, for the URL `/Users/me/foo/.git`, `directory`
126+
# will be set to `foo`.
115127
#
116128
# @param [Hash] options The options for this command (see list of valid
117129
# options below)
@@ -158,8 +170,10 @@ def self.bare(git_dir, options = {})
158170
# @return [Git::Base] an object that can execute git commands in the context
159171
# of the cloned local working copy or cloned repository.
160172
#
161-
def self.clone(repository, name, options = {})
162-
Base.clone(repository, name, options)
173+
def self.clone(repository_url, directory = nil, options = {})
174+
clone_to_options = options.select { |key, _value| %i[bare mirror].include?(key) }
175+
directory ||= Git::URL.clone_to(repository_url, **clone_to_options)
176+
Base.clone(repository_url, directory, options)
163177
end
164178

165179
# Export the current HEAD (or a branch, if <tt>options[:branch]</tt>

lib/git/base.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ def self.bare(git_dir, options = {})
1717
end
1818

1919
# (see Git.clone)
20-
def self.clone(repository, name, options = {})
21-
new_options = Git::Lib.new(nil, options[:log]).clone(repository, name, options)
20+
def self.clone(repository_url, directory, options = {})
21+
new_options = Git::Lib.new(nil, options[:log]).clone(repository_url, directory, options)
2222
normalize_paths(new_options, bare: options[:bare] || options[:mirror])
23-
self.new(new_options)
23+
new(new_options)
2424
end
2525

2626
# Returns (and initialize if needed) a Git::Config instance

lib/git/lib.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ def init(opts={})
9595
#
9696
# @return [Hash] the options to pass to {Git::Base.new}
9797
#
98-
def clone(repository, name, opts = {})
98+
def clone(repository_url, directory, opts = {})
9999
@path = opts[:path] || '.'
100-
clone_dir = opts[:path] ? File.join(@path, name) : name
100+
clone_dir = opts[:path] ? File.join(@path, directory) : directory
101101

102102
arr_opts = []
103103
arr_opts << '--bare' if opts[:bare]
@@ -106,11 +106,11 @@ def clone(repository, name, opts = {})
106106
arr_opts << '--config' << opts[:config] if opts[:config]
107107
arr_opts << '--origin' << opts[:remote] || opts[:origin] if opts[:remote] || opts[:origin]
108108
arr_opts << '--recursive' if opts[:recursive]
109-
arr_opts << "--mirror" if opts[:mirror]
109+
arr_opts << '--mirror' if opts[:mirror]
110110

111111
arr_opts << '--'
112112

113-
arr_opts << repository
113+
arr_opts << repository_url
114114
arr_opts << clone_dir
115115

116116
command('clone', arr_opts)

tests/units/test_git_clone.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
require 'test/unit'
4+
require_relative '../test_helper'
5+
6+
# Tests for Git.clone
7+
class TestGitClone < Test::Unit::TestCase
8+
def setup_repo
9+
Git.init('repository.git', bare: true)
10+
git = Git.clone('repository.git', 'temp')
11+
File.write('temp/test.txt', 'test')
12+
git.add('test.txt')
13+
git.commit('Initial commit')
14+
end
15+
16+
def test_git_clone_with_name
17+
in_temp_dir do |path|
18+
setup_repo
19+
clone_dir = 'clone_to_this_dir'
20+
git = Git.clone('repository.git', clone_dir)
21+
assert(Dir.exist?(clone_dir))
22+
expected_dir = File.realpath(clone_dir)
23+
assert_equal(expected_dir, git.dir.to_s)
24+
end
25+
end
26+
27+
def test_git_clone_with_no_name
28+
in_temp_dir do |path|
29+
setup_repo
30+
git = Git.clone('repository.git')
31+
assert(Dir.exist?('repository'))
32+
expected_dir = File.realpath('repository')
33+
assert_equal(expected_dir, git.dir.to_s)
34+
end
35+
end
36+
end

0 commit comments

Comments
 (0)