class GitPulls
Constants
- GIT_PATH
- GIT_REMOTE
- PULLS_CACHE_FILE
Public Class Methods
new(args)
click to toggle source
# File lib/git-pulls.rb, line 14 def initialize(args) @command = args.shift @user, @repo = repo_info @args = args end
start(args)
click to toggle source
# File lib/git-pulls.rb, line 20 def self.start(args) GitPulls.new(args).run end
Public Instance Methods
browse()
click to toggle source
# File lib/git-pulls.rb, line 160 def browse num = @args.shift if pull = pull_num(num) Launchy.open(pull[:_links].to_hash[:html].to_hash[:href]) else puts "No such number" end end
cache_pull_info()
click to toggle source
# File lib/git-pulls.rb, line 345 def cache_pull_info response_o = Octokit.pull_requests("#{@user}/#{@repo}", 'open') response_c = Octokit.pull_requests("#{@user}/#{@repo}", 'closed') save_data({'open' => response_o, 'closed' => response_c}, PULLS_CACHE_FILE) end
checkout()
click to toggle source
# File lib/git-pulls.rb, line 205 def checkout puts "Checking out all open pull requests for #{@user}/#{@repo}" pulls = get_open_pull_info pulls.each do |pull| head = pull[:head].to_hash branch_ref = head[:ref] puts "> #{branch_ref} into pull-#{branch_ref}" git("branch --track #{@args.join(' ')} pull-#{branch_ref} #{GIT_REMOTE}/#{branch_ref}") end end
clean(info)
click to toggle source
# File lib/git-pulls.rb, line 276 def clean(info) info.to_s.gsub("\n", ' ') end
configure()
click to toggle source
PRIVATE REPOSITORIES ACCESS
# File lib/git-pulls.rb, line 282 def configure Octokit.configure do |config| config.login = github_login if github_login and not github_login.empty? config.web_endpoint = github_endpoint config.access_token = github_token if github_token and not github_token.empty? config.proxy = github_proxy if github_proxy and not github_proxy.empty? config.api_endpoint = github_api_endpoint if (github_api_endpoint and \ not github_api_endpoint.empty?) end end
enterprise_user_and_proj(u)
click to toggle source
# File lib/git-pulls.rb, line 384 def enterprise_user_and_proj(u) # if git, u is probably something like: git@github.hq.corp.lan:SomeGroup/some_repo.git m = /.*?:(.*)\/(.*)/.match(u) if u =~ /^git/ # if http(s), u is probably something like: https://github.hq.corp.lan/SomeGroup/some_repo.git m = /https?:\/\/.*?\/(.*)\/(.*)/.match(u) if u =~ /^http/ if m return m[1], m[2].sub(/\.git\Z/, "") end return nil, nil end
fetch_stale_forks()
click to toggle source
# File lib/git-pulls.rb, line 224 def fetch_stale_forks puts "Checking for forks in need of fetching" pulls = get_open_pull_info | get_closed_pull_info repos = {} pulls.each do |pull| head = pull[:head].to_hash unless repo = head[:repo] && head[:repo].to_hash next # Fork has been deleted end owner = repo[:owner].to_hash repo_name = repo[:name] sha = head[:sha] unless has_sha?(sha) repo = "#{owner[:login]}/#{repo_name}" repos[repo] = true end end if github_credentials_provided? endpoint = "git@github.com:" else endpoint = github_endpoint + "/" end repos.each do |repo, bool| puts " fetching #{repo}" git("fetch #{endpoint}#{repo}.git +refs/heads/*:refs/pr/#{repo}/*") end end
get_closed_pull_info()
click to toggle source
# File lib/git-pulls.rb, line 333 def get_closed_pull_info get_data(PULLS_CACHE_FILE)['closed'].map(&:to_hash) end
get_data(file)
click to toggle source
# File lib/git-pulls.rb, line 341 def get_data(file) ::Psych.load_file(file) end
get_open_pull_info()
click to toggle source
# File lib/git-pulls.rb, line 337 def get_open_pull_info get_data(PULLS_CACHE_FILE)['open'].map(&:to_hash) end
git(command)
click to toggle source
# File lib/git-pulls.rb, line 416 def git(command) `git #{command}`.chomp end
github_api_endpoint()
click to toggle source
# File lib/git-pulls.rb, line 310 def github_api_endpoint endpoint = git("config --get-all github.api") if endpoint.size > 0 endpoint else 'https://api.github.com' end end
github_credentials_provided?()
click to toggle source
API/DATA HELPER FUNCTIONS #
# File lib/git-pulls.rb, line 326 def github_credentials_provided? if github_token.empty? && github_login.empty? return false end true end
github_endpoint()
click to toggle source
# File lib/git-pulls.rb, line 302 def github_endpoint host = git("config --get-all github.host") if host.size > 0 host else 'https://github.com' end end
github_insteadof_matching(c, u)
click to toggle source
# File lib/git-pulls.rb, line 363 def github_insteadof_matching(c, u) first = c.collect {|k,v| [v, /url\.(.*github\.com.*)\.insteadof/.match(k)]}. find {|v,m| v and u.index(v) and m != nil} if first return first[0], first[1][1] end return nil, nil end
github_login()
click to toggle source
# File lib/git-pulls.rb, line 294 def github_login git("config --get-all github.user") end
github_proxy()
click to toggle source
# File lib/git-pulls.rb, line 320 def github_proxy git("config --get-all http.proxy") end
github_token()
click to toggle source
# File lib/git-pulls.rb, line 298 def github_token git("config --get-all github.token") end
github_user_and_proj(u)
click to toggle source
# File lib/git-pulls.rb, line 373 def github_user_and_proj(u) # Trouble getting optional ".git" at end to work, so put that logic below m = /github\.com.(.*?)\/(.*)/.match(u) if m return m[1], m[2].sub(/\.git\Z/, "") end # that works with default github but not enterprise return enterprise_user_and_proj(u) end
has_sha?(sha)
click to toggle source
# File lib/git-pulls.rb, line 256 def has_sha?(sha) git("show #{sha} 2>&1") $?.exitstatus == 0 end
help()
click to toggle source
COMMANDS ##
# File lib/git-pulls.rb, line 44 def help puts "No command: #{@command}" puts "Try: update, list, show, merge, checkout, browse" puts "or call with '-h' for usage information" end
l(info, size)
click to toggle source
DISPLAY HELPER FUNCTIONS #
# File lib/git-pulls.rb, line 268 def l(info, size) clean(info)[0, size].ljust(size) end
list()
click to toggle source
# File lib/git-pulls.rb, line 169 def list state = @args.shift if not ['open', 'closed'].include?(state) state = 'open' option = state else option = @args.shift end puts state.capitalize + " Pull Requests for #{@user}/#{@repo}" pulls = state == 'open' ? get_open_pull_info : get_closed_pull_info if (state == 'closed') pulls.sort! { |a, b| b[:closed_at] <=> a[:closed_at] } end pulls.reverse! if option == '--reverse' pulls.each do |pull| pull = pull.to_hash head = pull[:head].to_hash line = [] line << l(pull[:number], 4) line << l(Date.parse(pull[:created_at].to_s).strftime("%m/%d"), 5) line << l(pull[:title], 35) line << l(head[:label], 50) puts line.join ' ' end if pulls.count == 0 puts ' -- no ' + state + ' pull requests --' end end
merge()
click to toggle source
# File lib/git-pulls.rb, line 65 def merge num = @args.shift option = @args.shift if pull = pull_num(num) head = pull[:head].to_hash user = pull[:user].to_hash if repo = head[:repo] && head[:repo].to_hash owner = repo[:owner].to_hash repo_name = repo[:name] sha = head[:sha] message = "Merge pull request ##{num} from #{owner[:login]}/#{repo_name}\n\n---\n\n" message += pull[:body] ? pull[:body].gsub("'", '') : "" cmd = '' if option == '--log' message += "\n\n---\n\nMerge Log:\n" puts cmd = "git merge --no-ff --log -m '#{message}' #{sha}" elsif option == '--no-commit' message += "\n\n---\n\nMerge with --no-commit option:\n" puts cmd = "git merge --no-commit -m '#{message}' #{sha}" else puts cmd = "git merge --no-ff -m '#{message}' #{sha}" end exec(cmd) else # they deleted the source repo owner = head[:user].to_hash[:login] patch_url = "#{pull[:_links].to_hash[:html].to_hash[:href]}.patch" puts "Sorry, #{owner} deleted the source repository, git-pulls doesn't support this." puts "You can manually patch your repo by running:" puts puts " curl #{patch_url} | git am" puts puts "Tell the contributor not to do this." return false end else puts "No such number" end end
not_a_github_repository()
click to toggle source
# File lib/git-pulls.rb, line 50 def not_a_github_repository puts "No user informations found. Make sure you're in a Github's repository." end
not_merged?(sha)
click to toggle source
# File lib/git-pulls.rb, line 261 def not_merged?(sha) commits = git("rev-list #{sha} ^HEAD 2>&1") commits.split("\n").size > 0 end
pull_num(num)
click to toggle source
# File lib/git-pulls.rb, line 357 def pull_num(num) pull = get_open_pull_info.select { |p| p[:number].to_s == num.to_s }.first pull ||= get_closed_pull_info.select { |p| p[:number].to_s == num.to_s }.first pull end
r(info, size)
click to toggle source
# File lib/git-pulls.rb, line 272 def r(info, size) clean(info)[0, size].rjust(size) end
repo_info()
click to toggle source
# File lib/git-pulls.rb, line 396 def repo_info c = {} config = git('config --list') config.split("\n").each do |line| k, v = line.split('=') c[k] = v end u = c["remote.#{GIT_REMOTE}.url"] user, proj = github_user_and_proj(u) if !(user and proj) short, base = github_insteadof_matching(c, u) if short and base u = u.sub(short, base) user, proj = github_user_and_proj(u) end end [user, proj] end
run()
click to toggle source
# File lib/git-pulls.rb, line 24 def run configure if not @user not_a_github_repository elsif @command && self.respond_to?(@command) # If the cache file doesn't exist, make sure we run update # before any other command. git-pulls will otherwise crash # with an exception. update unless File.exists?(PULLS_CACHE_FILE) || @command == 'update' self.send @command elsif %w(-h --help).include?(@command) usage else help end end
save_data(data, file)
click to toggle source
# File lib/git-pulls.rb, line 351 def save_data(data, file) File.open(file, "w+") do |f| f.puts Psych.dump(data) end end
show()
click to toggle source
# File lib/git-pulls.rb, line 109 def show num = @args.shift optiona = @args.shift optionb = @args.shift if pull = pull_num(num) head = pull[:head].to_hash repo = head[:repo].to_hash user = pull[:user].to_hash comments = [] if optiona == '--comments' || optionb == '--comments' i_comments = Octokit.issue_comments("#{@user}/#{@repo}", num).map(&:to_hash) p_comments = Octokit.pull_request_comments("#{@user}/#{@repo}", num).map(&:to_hash) c_comments = Octokit.commit_comments(repo[:full_name], head[:sha]) comments = (i_comments | p_comments | c_comments).sort_by {|i| i[:created_at]} end puts "Number : #{pull[:number]}" puts "Label : #{head[:label]}" puts "Creator : #{user[:login]}" puts "Created : #{pull[:created_at]}" puts puts "Title : #{pull[:title]}" puts puts pull[:body] puts puts '------------' puts comments.each do |comment| user = comment[:user] puts "Comment : #{user[:login]}" puts "Created : #{comment[:created_at]}" puts "File : #{comment[:path]}:L#{comment[:line] || comment[:position] || comment[:original_position]}" unless comment[:path].nil? puts puts comment[:body] puts puts '------------' puts end if optiona == '--full' || optionb == '--full' exec "git diff --color=always HEAD...#{head[:sha]}" else puts "cmd: git diff HEAD...#{head[:sha]}" puts git("diff --stat --color=always HEAD...#{head[:sha]}") end else puts "No such number" end end
update()
click to toggle source
# File lib/git-pulls.rb, line 217 def update puts "Updating #{@user}/#{@repo}" cache_pull_info fetch_stale_forks list end
usage()
click to toggle source
# File lib/git-pulls.rb, line 54 def usage puts <<-USAGE Usage: git pulls update or: git pulls list [state] [--reverse] or: git pulls show <number> [--comments] [--full] or: git pulls browse <number> or: git pulls merge <number> [--no-commit] [--log] or: git pulls checkout [--force] USAGE end