Skip to content

Instantly share code, notes, and snippets.

@jcayzac
Created August 12, 2011 10:44
Show Gist options
  • Save jcayzac/1141843 to your computer and use it in GitHub Desktop.
Save jcayzac/1141843 to your computer and use it in GitHub Desktop.
Git subcommand to create GitHub pull request (place it in your PATH)
source "http://rubygems.org"
octokit
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'tempfile'
require 'octokit'
class GitPullRequest
@@branch_owner_re = /github\.com.(.*?)\/(.*)/
def git(command)
`git #{command}`.chomp
end
def branch_owner(branch)
remote = git("config branch.#{branch}.remote")
url = git("config remote.#{remote}.url")
m = @@branch_owner_re.match(url)
if m
return m[1], m[2].sub(/\.git\Z/, "")
end
return nil, nil
end
def run
github_token = git("config --get-all github.token")
if github_token.size == 0
abort <<-eot
Could not find value for key "github.token" in git's configuration.
eot
end
upstream = 'develop'
message = ''
OptionParser.new do |opts|
opts.on("-m", "--message msg", "Set this pull request's title") do |msg|
message = msg
end
opts.on("-u", "--upstream branch", "Set the upstream branch (default: develop)") do |up|
upstream = up
end
opts.on("-h", "--help", "Show usage") do
abort <<-eot
Usage:
git create-pull-request [-m msg] [-u branchname] [-h]
Creates a pull request based on the current locally-tracked branch.
-m, --message=msg Set the pull request's title (and no body).
-u, --upstream=branchname Set the upstream branch. Defaults to 'develop'.
-h, --help Display this help page and exits.
eot
end
end.parse!
team, repo_name = branch_owner(upstream)
if not team or not repo_name
abort <<-eot
Could not deduce upstream repository from branch #{upstream}. Bad remote?
eot
end
branch = git('symbolic-ref HEAD').split('/')[-1]
user, fork_name = branch_owner(branch)
if repo_name != fork_name
abort <<-eot
#{user}/#{fork_name} doesn't look like a fork of #{team}/#{repo_name}.
eot
end
if not user
user = git("config --get-all github.user")
end
if not user
abort <<-eot
Could not deduce your GitHub user name from branch #{branch}, \
and no value was found in Git's configuration for key "github.user".
eot
end
Octokit.configure do |config|
config.login = user
config.token = github_token
end
title = ''
body = ''
if message.size > 0
title = message
else
f = Tempfile.new('pull-request-message')
path = f.path
f.puts ''
f.puts ''
f.puts "# Please enter the pull request message. Lines starting"
f.puts "# with '#' will be ignored, and an empty message aborts"
f.puts "# the pull request."
f.puts "#"
f.puts "# Asks to apply branch:"
f.puts "# #{user}/#{repo_name}:#{branch}"
f.puts "# Onto branch:"
f.puts "# #{team}/#{repo_name}:#{upstream}"
f.puts "#"
f.puts "# vim: set filetype=gitcommit :"
f.flush
f.close
if not system("#{ENV['EDITOR']} #{path}")
File.delete(path)
abort "#{ENV['EDITOR']} exited with non-zero return code, aborting..."
end
f = File.open(path, "r")
lines = f.read.split("\n")
f.close
File.delete(path)
title_ = []
body_ = []
jumps = 0
lines.each do |line|
chomped = line.chomp
next if chomped.size > 0 and chomped[0].chr == '#'
if chomped.size == 0
jumps = jumps + 1
end
if jumps == 0
break if chomped.size == 0
title_ << chomped
else
next if chomped.size == 0
body_ << line
end
end
title = title_.join(' ')
body = body_.join("\n")
end
if title.size == 0
abort "No message, aborting!"
end
Octokit.create_pull_request(
"#{team}/#{repo_name}",
"#{team}:#{upstream}",
"#{user}:#{branch}",
"#{title}",
"#{body}"
)
end
end
GitPullRequest.new().run
# vim: set fileencodings=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment