/tools/bitbucket_pullrequests
Ruby | 235 lines | 192 code | 23 blank | 20 comment | 20 complexity | 64345cbe0464edef5e62c70f3c763946 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0
- #!/usr/bin/env ruby
- #/ Usage: <progname> [options]...
- #/ Get info on pull requests from gazebo's bitbucket repository
- # based on http://www.alphadevx.com/a/88-Writing-a-REST-Client-in-Ruby
- # to install dependencies on Ubuntu (tested with Precise, Quantal, and Raring):
- #sudo apt-get install rubygems ruby-rest-client ruby-json
- require 'rubygems'
- require 'rest_client'
- require 'json'
- require 'optparse'
- require 'date'
- $stderr.sync = true
- class BitbucketPullRequests
- # Pull request summary
- class Summary
- attr_reader :id
- attr_reader :source
- attr_reader :destination
- attr_reader :branch
- attr_reader :createdOn
- attr_reader :title
- def initialize(jsonHash, options)
- @options = options
- @id = jsonHash["id"]
- @source = " "*12
- @destination = " "*12
- @branch = ""
- @title = ""
- source = jsonHash["source"]["commit"]
- destination = jsonHash["destination"]["commit"]
- branch = jsonHash["source"]["branch"]
- title = jsonHash["title"]
- @source = source["hash"] if !source.nil?
- @destination = destination["hash"] if !destination.nil?
- @branch = branch["name"] if !branch.nil?
- @title = title if !title.nil?
- @createdOn = jsonHash["created_on"]
- end
- def to_s
- title = ""
- title += "\n" + @title + "\n" if @options["title"]
- title +
- @id.to_s.rjust(5, ' ') + " " +
- DateTime.parse(@createdOn).strftime("%Y-%m-%d") + " " +
- @source + " " +
- @destination + " " +
- @branch + "\n"
- end
- def date_and_string
- [@createdOn, self.to_s]
- end
- end
- # constructor
- def initialize(options)
- @url_pullrequests = 'https://bitbucket.org/api/2.0/repositories/osrf/gazebo/pullrequests'
- @options = options
- end
- # helpers for RestClient.get calls
- def getUrl(url)
- puts url if @options["show-url"]
- RestClient.get(url)
- end
- def getJson(url)
- json = JSON.parse(getUrl(url).body)
- if @options["verbose"]
- puts JSON.pretty_generate(json)
- end
- json
- end
- # summary of open pull requests
- def listPullRequests()
- jsonHash = getJson(@url_pullrequests + "/?state=OPEN")
- output = ""
- # Hash of pull requests.
- pullrequests = {}
- jsonHash["values"].each { |pr|
- date, str = Summary.new(pr, @options).date_and_string
- pullrequests[date] = str
- }
- while jsonHash.has_key? "next"
- jsonHash = getJson(jsonHash["next"])
- jsonHash["values"].each { |pr|
- date, str = Summary.new(pr, @options).date_and_string
- pullrequests[date] = str
- }
- end
- # Generate output sorted by creation time
- pullrequests.keys.sort.each { |k| output += pullrequests[k] }
- return output
- end
- # summary of one pull request
- def getPullRequestSummary(id)
- jsonHash = getJson(@url_pullrequests + "/" + id.to_s)
- return Summary.new(jsonHash, @options)
- end
- # diff of pull request
- def getPullRequestDiff(id)
- response = getUrl(@url_pullrequests + "/" + id.to_s + "/diff")
- puts response if @options["verbose"]
- return response
- end
- # list of files changed by pull request
- def getPullRequestFiles(id)
- files = []
- diff = getPullRequestDiff(id)
- diff.lines.map(&:chomp).each do |line|
- if line.start_with? '+++ b/'
- line["+++ b/"] = ""
- files << line
- end
- end
- return files
- end
- # get ids for open pull requests
- def getOpenPullRequests()
- jsonHash = getJson(@url_pullrequests + "/?state=OPEN")
- ids = []
- jsonHash["values"].each { |pr| ids << pr["id"].to_i }
- while jsonHash.has_key? "next"
- jsonHash = getJson(jsonHash["next"])
- jsonHash["values"].each { |pr| ids << pr["id"].to_i }
- end
- return ids
- end
- # check changed files in pull request by id
- def checkPullRequest(id, fork=true)
- summary = getPullRequestSummary(id)
- puts "checking pull request #{id}, branch #{summary.branch}"
- files = getPullRequestFiles(id)
- files_list = ""
- files.each { |f| files_list += " " + f }
- hg_root = `hg root`.chomp
- `hg log -r #{summary.destination} 2>&1`
- if $? != 0
- puts "Unknown revision #{summary.destination}, try: hg pull"
- return
- end
- `hg log -r #{summary.source} 2>&1`
- if $? != 0
- puts "Unknown revision #{summary.source}, try: hg pull " +
- "(it could also be a fork)"
- return
- end
- ancestor=`hg log -r "ancestor(#{summary.source},#{summary.destination})" | head -1 | sed -e 's@.*:@@'`.chomp
- if ancestor != summary.destination
- puts "Need to merge branch #{summary.branch} with #{summary.destination}"
- end
- if fork
- # this will allow real-time console output
- exec "echo #{files_list} | sh #{hg_root}/tools/code_check.sh --quick #{summary.source}"
- else
- puts `echo #{files_list} | sh "#{hg_root}"/tools/code_check.sh --quick #{summary.source}`
- end
- end
- end
- # default options
- options = {}
- options["list"] = false
- options["summary"] = nil
- options["check"] = false
- options["check_id"] = nil
- options["diff"] = nil
- options["files"] = nil
- options["show-url"] = false
- options["title"] = false
- options["verbose"] = false
- opt_parser = OptionParser.new do |o|
- o.on("-l", "--list",
- "List open pull requests with fields:\n" + " "*37 +
- "[id] [source] [dest] [branch]") { |o| options["list"] = o }
- o.on("-c", "--check [id]", Integer,
- "") { |o| options["check_id"] = o; options["check"] = true }
- o.on("-d", "--diff [id]", Integer,
- "Show diff from pull request") { |o| options["diff"] = o }
- o.on("-f", "--files [id]", Integer,
- "Show changed files in a pull request") { |o| options["files"] = o }
- o.on("-s", "--summary [id]", Integer,
- "Summarize a pull request with fields:\n" + " "*37 +
- "[id] [source] [dest] [branch]") { |o| options["summary"] = o }
- o.on("-t", "--title",
- "Show pull request title with --list, --summary") { |o| options["title"] = o }
- o.on("-u", "--show-url",
- "Show urls accessed") { |o| options["show-url"] = o }
- o.on("-v", "--verbose",
- "Verbose output") { |o| options["verbose"] = o }
- o.on("-h", "--help", "Display this help message") do
- puts opt_parser
- exit
- end
- end
- opt_parser.parse!
- client = BitbucketPullRequests.new(options)
- if options["list"]
- puts client.listPullRequests()
- elsif !options["summary"].nil?
- puts client.getPullRequestSummary(options["summary"])
- elsif !options["diff"].nil?
- puts client.getPullRequestDiff(options["diff"])
- elsif !options["files"].nil?
- puts client.getPullRequestFiles(options["files"])
- elsif options["check"]
- if options["check_id"].nil?
- # check all open pull requests
- client.getOpenPullRequests().each { |id|
- client.checkPullRequest(id, false)
- }
- else
- client.checkPullRequest(options["check_id"])
- end
- else
- puts opt_parser
- end