diff --git a/features/pull_request.feature b/features/pull_request.feature index 39f7a815e75a0d90d94f0e4be083d24617cbe48d..a7c9fdcd56c74b81953be2f566ef1727a97747d2 100644 --- a/features/pull_request.feature +++ b/features/pull_request.feature @@ -560,3 +560,15 @@ Feature: hub pull-request """ When I successfully run `hub pull-request -m hereyougo` Then the output should contain exactly "the://url\n" + + Scenario: Branch with quotation mark in name + Given I am on the "feat'ure" branch with upstream "origin/feat'ure" + Given the GitHub API server: + """ + post('/repos/mislav/coral/pulls') { + assert :head => "mislav:feat'ure" + json :html_url => "the://url" + } + """ + When I successfully run `hub pull-request -m hereyougo` + Then the output should contain exactly "the://url\n" diff --git a/features/steps.rb b/features/steps.rb index b3cf3efe2ea895cad1c1c777fff03f4263aed51c..c6aa4b9a90500ce545e23cd5eb1c0a23a2b9b2b9 100644 --- a/features/steps.rb +++ b/features/steps.rb @@ -96,7 +96,7 @@ Given(/^I am on the "([^"]+)" branch(?: (pushed to|with upstream) "([^"]+)")?$/) end unless upstream == 'refs/heads/master' end track = type == 'pushed to' ? '--no-track' : '--track' - run_silent %(git checkout --quiet -B #{name} #{track} #{upstream}) + run_silent %(git checkout --quiet -B #{shell_escape name} #{track} #{shell_escape upstream}) end Given(/^the default branch for "([^"]+)" is "([^"]+)"$/) do |remote, branch| diff --git a/features/support/env.rb b/features/support/env.rb index 01bef3d404e9ba5f6919cc0c51a8c608ff61ed57..d7367f7a0645624ced136ba89df0c627e5bdefb5 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -149,4 +149,8 @@ World Module.new { def announcer @announcer ||= super end + + def shell_escape(message) + message.to_s.gsub(/['"\\ $]/) { |m| "\\#{m}" } + end } diff --git a/lib/hub/commands.rb b/lib/hub/commands.rb index 7e92cc27593bce42880ec890ff14af05d7603294..c8b850012038c8bf942b0111bff675e24b8aa33b 100644 --- a/lib/hub/commands.rb +++ b/lib/hub/commands.rb @@ -86,7 +86,7 @@ module Hub abort "Aborted: the origin remote doesn't point to a GitHub repository." end - unless sha = local_repo.git_command("rev-parse -q #{ref}") + unless sha = local_repo.git_command("rev-parse -q '%s'" % ref.gsub("'", "\\'")) abort "Aborted: no revision could be determined from '#{ref}'" end @@ -228,8 +228,11 @@ module Hub else format = '%h (%aN, %ar)%n%w(78,3,3)%s%n%+b' default_message = nil - commit_summary = git_command "log --no-color --format='%s' --cherry %s...%s" % - [format, base_branch, remote_branch] + commit_summary = git_command "log --no-color --format='%s' --cherry '%s...%s'" % [ + format, + base_branch.to_s.gsub("'", "\\'"), + remote_branch.to_s.gsub("'", "\\'") + ] end options[:title], options[:body] = pullrequest_editmsg(commit_summary) { |msg, initial_message, cc| diff --git a/lib/hub/context.rb b/lib/hub/context.rb index 7faed2c8e234fe8bf7d8531ffcb6771f1ec1259c..f0980513f4dca036a00a22b75494f0a7cbd3eeca 100644 --- a/lib/hub/context.rb +++ b/lib/hub/context.rb @@ -355,7 +355,8 @@ module Hub end def upstream - if branch = local_repo.git_command("rev-parse --symbolic-full-name #{short_name}@{upstream}") + escaped_name = short_name.gsub("'", "\\'") + if branch = local_repo.git_command("rev-parse --symbolic-full-name '#{escaped_name}@{upstream}'") Branch.new local_repo, branch end end @@ -479,7 +480,10 @@ module Hub end def rev_list(a, b) - git_command("rev-list --cherry-pick --right-only --no-merges #{a}...#{b}") + git_command "rev-list --cherry-pick --right-only --no-merges '%s...%s'" % [ + a.to_s.gsub("'", "\\'"), + b.to_s.gsub("'", "\\'") + ] end PWD = Dir.pwd