Skip to content

Commit 3f05c22

Browse files
author
Douwe Maan
committed
Merge branch 'rs-git-bin-path' into 'master'
Replace all usages of `git` command with configurable binary path Closes #3311 See merge request !1742
2 parents 82aa541 + d09d62b commit 3f05c22

File tree

12 files changed

+46
-36
lines changed

12 files changed

+46
-36
lines changed

app/models/repository.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def commits_between(from, to)
8989

9090
def find_commits_by_message(query)
9191
# Limited to 1000 commits for now, could be parameterized?
92-
args = %W(git log --pretty=%H --max-count 1000 --grep=#{query})
92+
args = %W(#{Gitlab.config.git.bin_path} log --pretty=%H --max-count 1000 --grep=#{query})
9393

9494
git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp)
9595
commits = git_log_results.map { |c| commit(c) }
@@ -296,7 +296,7 @@ def submodule_url_for(ref, path)
296296
end
297297

298298
def last_commit_for_path(sha, path)
299-
args = %W(git rev-list --max-count=1 #{sha} -- #{path})
299+
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
300300
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
301301
commit(sha)
302302
end
@@ -347,7 +347,7 @@ def prev_blob_for_diff(commit, diff)
347347
end
348348

349349
def branch_names_contains(sha)
350-
args = %W(git branch --contains #{sha})
350+
args = %W(#{Gitlab.config.git.bin_path} branch --contains #{sha})
351351
names = Gitlab::Popen.popen(args, path_to_repo).first
352352

353353
if names.respond_to?(:split)
@@ -364,7 +364,7 @@ def branch_names_contains(sha)
364364
end
365365

366366
def tag_names_contains(sha)
367-
args = %W(git tag --contains #{sha})
367+
args = %W(#{Gitlab.config.git.bin_path} tag --contains #{sha})
368368
names = Gitlab::Popen.popen(args, path_to_repo).first
369369

370370
if names.respond_to?(:split)
@@ -505,7 +505,7 @@ def merge_base(first_commit_id, second_commit_id)
505505

506506
def search_files(query, ref)
507507
offset = 2
508-
args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
508+
args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
509509
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
510510
end
511511

@@ -537,7 +537,7 @@ def parse_search_result(result)
537537
end
538538

539539
def fetch_ref(source_path, source_ref, target_ref)
540-
args = %W(git fetch -f #{source_path} #{source_ref}:#{target_ref})
540+
args = %W(#{Gitlab.config.git.bin_path} fetch -f #{source_path} #{source_ref}:#{target_ref})
541541
Gitlab::Popen.popen(args, path_to_repo)
542542
end
543543

config/initializers/2_app.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module Gitlab
2-
VERSION = File.read(Rails.root.join("VERSION")).strip
3-
REVISION = Gitlab::Popen.popen(%W(git log --pretty=format:%h -n 1)).first.chomp
4-
52
def self.config
63
Settings
74
end
5+
6+
VERSION = File.read(Rails.root.join("VERSION")).strip
7+
REVISION = Gitlab::Popen.popen(%W(#{config.git.bin_path} log --pretty=format:%h -n 1)).first.chomp
88
end

doc/development/shell_commands.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ Gitlab::Popen.popen(%W(find /some/path -not -path /some/path -mmin +120 -delete)
3535

3636
This coding style could have prevented CVE-2013-4490.
3737

38+
## Always use the configurable git binary path for git commands
39+
40+
```ruby
41+
# Wrong
42+
system(*%W(git branch -d -- #{branch_name}))
43+
44+
# Correct
45+
system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name}))
46+
```
47+
3848
## Bypass the shell by splitting commands into separate tokens
3949

4050
When we pass shell commands as a single string to Ruby, Ruby will let `/bin/sh` evaluate the entire string. Essentially, we are asking the shell to evaluate a one-line script. This creates a risk for shell injection attacks. It is better to split the shell command into tokens ourselves. Sometimes we use the scripting capabilities of the shell to change the working directory or set environment variables. All of this can also be achieved securely straight from Ruby
@@ -81,9 +91,9 @@ In the GitLab codebase, we avoid the option/argument ambiguity by _always_ using
8191

8292
```ruby
8393
# Wrong
84-
system(*%W(git branch -d #{branch_name}))
94+
system(*%W(#{Gitlab.config.git.bin_path} branch -d #{branch_name}))
8595
# Correct
86-
system(*%W(git branch -d -- #{branch_name}))
96+
system(*%W(#{Gitlab.config.git.bin_path} branch -d -- #{branch_name}))
8797
```
8898

8999
This coding style could have prevented CVE-2013-4582.
@@ -94,9 +104,9 @@ Capturing the output of shell commands with backticks reads nicely, but you are
94104

95105
```ruby
96106
# Wrong
97-
logs = `cd #{repo_dir} && git log`
107+
logs = `cd #{repo_dir} && #{Gitlab.config.git.bin_path} log`
98108
# Correct
99-
logs, exit_status = Gitlab::Popen.popen(%W(git log), repo_dir)
109+
logs, exit_status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} log), repo_dir)
100110

101111
# Wrong
102112
user = `whoami`
@@ -108,7 +118,7 @@ In other repositories, such as gitlab-shell you can also use `IO.popen`.
108118

109119
```ruby
110120
# Safe IO.popen example
111-
logs = IO.popen(%W(git log), chdir: repo_dir) { |p| p.read }
121+
logs = IO.popen(%W(#{Gitlab.config.git.bin_path} log), chdir: repo_dir) { |p| p.read }
112122
```
113123

114124
Note that unlike `Gitlab::Popen.popen`, `IO.popen` does not capture standard error.

lib/backup/repository.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def dump
3535
if wiki.repository.empty?
3636
$progress.puts " [SKIPPED]".cyan
3737
else
38-
cmd = %W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all)
38+
cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all)
3939
output, status = Gitlab::Popen.popen(cmd)
4040
if status.zero?
4141
$progress.puts " [DONE]".green
@@ -67,7 +67,7 @@ def restore
6767
FileUtils.mkdir_p(path_to_repo(project))
6868
cmd = %W(tar -xf #{path_to_bundle(project)} -C #{path_to_repo(project)})
6969
else
70-
cmd = %W(git init --bare #{path_to_repo(project)})
70+
cmd = %W(#{Gitlab.config.git.bin_path} init --bare #{path_to_repo(project)})
7171
end
7272

7373
if system(*cmd, silent)
@@ -87,7 +87,7 @@ def restore
8787
# that was initialized with ProjectWiki.new() and then
8888
# try to restore with 'git clone --bare'.
8989
FileUtils.rm_rf(path_to_repo(wiki))
90-
cmd = %W(git clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)})
90+
cmd = %W(#{Gitlab.config.git.bin_path} clone --bare #{path_to_bundle(wiki)} #{path_to_repo(wiki)})
9191

9292
if system(*cmd, silent)
9393
$progress.puts " [DONE]".green

lib/gitlab/force_push_check.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def self.force_push?(project, oldrev, newrev)
77
if Gitlab::Git.blank_ref?(oldrev) || Gitlab::Git.blank_ref?(newrev)
88
false
99
else
10-
missed_refs, _ = Gitlab::Popen.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
10+
missed_refs, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev}))
1111
missed_refs.split("\n").size > 0
1212
end
1313
end

lib/gitlab/git_ref_validator.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module GitRefValidator
66
# Returns true for a valid reference name, false otherwise
77
def validate(ref_name)
88
Gitlab::Utils.system_silent(
9-
%W(git check-ref-format refs/#{ref_name}))
9+
%W(#{Gitlab.config.git.bin_path} check-ref-format refs/#{ref_name}))
1010
end
1111
end
1212
end

lib/gitlab/upgrader.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ def latest_version_raw
5050
end
5151

5252
def fetch_git_tags
53-
remote_tags, _ = Gitlab::Popen.popen(%W(git ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
53+
remote_tags, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
5454
remote_tags.split("\n").grep(/tags\/v#{current_version.major}/)
5555
end
5656

5757
def update_commands
5858
{
59-
"Stash changed files" => %W(git stash),
60-
"Get latest code" => %W(git fetch),
61-
"Switch to new version" => %W(git checkout v#{latest_version}),
59+
"Stash changed files" => %W(#{Gitlab.config.git.bin_path} stash),
60+
"Get latest code" => %W(#{Gitlab.config.git.bin_path} fetch),
61+
"Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}),
6262
"Install gems" => %W(bundle),
6363
"Migrate DB" => %W(bundle exec rake db:migrate),
6464
"Recompile assets" => %W(bundle exec rake assets:clean assets:precompile),

lib/tasks/gitlab/check.rake

+1-1
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ namespace :gitlab do
824824
repo_dirs = Dir.glob(File.join(namespace_dir, '*'))
825825
repo_dirs.each do |dir|
826826
puts "\nChecking repo at #{dir}"
827-
system(*%w(git fsck), chdir: dir)
827+
system(*%W(#{Gitlab.config.git.bin_path} fsck), chdir: dir)
828828
end
829829
end
830830
end

lib/tasks/gitlab/shell.rake

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace :gitlab do
1717

1818
# Clone if needed
1919
unless File.directory?(target_dir)
20-
system(*%W(git clone -- #{args.repo} #{target_dir}))
20+
system(*%W(#{Gitlab.config.git.bin_path} clone -- #{args.repo} #{target_dir}))
2121
end
2222

2323
# Make sure we're on the right tag
@@ -27,7 +27,7 @@ namespace :gitlab do
2727
reseted = reset_to_commit(args)
2828

2929
unless reseted
30-
system(*%W(git fetch origin))
30+
system(*%W(#{Gitlab.config.git.bin_path} fetch origin))
3131
reset_to_commit(args)
3232
end
3333

@@ -128,14 +128,14 @@ namespace :gitlab do
128128
end
129129

130130
def reset_to_commit(args)
131-
tag, status = Gitlab::Popen.popen(%W(git describe -- #{args.tag}))
131+
tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- #{args.tag}))
132132

133133
unless status.zero?
134-
tag, status = Gitlab::Popen.popen(%W(git describe -- origin/#{args.tag}))
134+
tag, status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} describe -- origin/#{args.tag}))
135135
end
136136

137137
tag = tag.strip
138-
system(*%W(git reset --hard #{tag}))
138+
system(*%W(#{Gitlab.config.git.bin_path} reset --hard #{tag}))
139139
end
140140
end
141141

spec/models/project_wiki_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@
223223

224224
def create_temp_repo(path)
225225
FileUtils.mkdir_p path
226-
system(*%W(git init --quiet --bare -- #{path}))
226+
system(*%W(#{Gitlab.config.git.bin_path} init --quiet --bare -- #{path}))
227227
end
228228

229229
def remove_temp_repo(path)

spec/requests/api/repositories_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
it 'should create a new annotated tag' do
3737
# Identity must be set in .gitconfig to create annotated tag.
3838
repo_path = project.repository.path_to_repo
39-
system(*%W(git --git-dir=#{repo_path} config user.name #{user.name}))
40-
system(*%W(git --git-dir=#{repo_path} config user.email #{user.email}))
39+
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.name #{user.name}))
40+
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.email #{user.email}))
4141

4242
post api("/projects/#{project.id}/repository/tags", user),
4343
tag_name: 'v7.1.0',

spec/support/test_env.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ def setup_repo(repo_path, repo_path_bare, repo_name, branch_sha)
9696
clone_url = "https://gitlab.com/gitlab-org/#{repo_name}.git"
9797

9898
unless File.directory?(repo_path)
99-
system(*%W(git clone -q #{clone_url} #{repo_path}))
99+
system(*%W(#{Gitlab.config.git.bin_path} clone -q #{clone_url} #{repo_path}))
100100
end
101101

102102
Dir.chdir(repo_path) do
103103
branch_sha.each do |branch, sha|
104104
# Try to reset without fetching to avoid using the network.
105-
reset = %W(git update-ref refs/heads/#{branch} #{sha})
105+
reset = %W(#{Gitlab.config.git.bin_path} update-ref refs/heads/#{branch} #{sha})
106106
unless system(*reset)
107-
if system(*%w(git fetch origin))
107+
if system(*%W(#{Gitlab.config.git.bin_path} fetch origin))
108108
unless system(*reset)
109109
raise 'The fetched test seed '\
110110
'does not contain the required revision.'
@@ -117,7 +117,7 @@ def setup_repo(repo_path, repo_path_bare, repo_name, branch_sha)
117117
end
118118

119119
# We must copy bare repositories because we will push to them.
120-
system(git_env, *%W(git clone -q --bare #{repo_path} #{repo_path_bare}))
120+
system(git_env, *%W(#{Gitlab.config.git.bin_path} clone -q --bare #{repo_path} #{repo_path_bare}))
121121
end
122122

123123
def copy_repo(project)

0 commit comments

Comments
 (0)