PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/bin/bb

https://bitbucket.org/osrf/bitbucket-client-tools
Ruby | 225 lines | 178 code | 19 blank | 28 comment | 20 complexity | d662023f85d8d49e1db8b654ced2b2bd MD5 | raw file
  1. #!/usr/bin/env ruby
  2. #/ Usage: <progname> [options]...
  3. #/ Get info about bitbucket repositories
  4. # based on http://www.alphadevx.com/a/88-Writing-a-REST-Client-in-Ruby
  5. # to install dependencies on Ubuntu (tested with Precise, Quantal, and Raring):
  6. #sudo apt-get install ruby1.9.1-dev rubygems
  7. #sudo gem install rest-client json
  8. require 'rubygems'
  9. require 'rest_client'
  10. require 'json'
  11. require 'optparse'
  12. $stderr.sync = true
  13. class BitbucketTools
  14. # Pull request summary
  15. class Summary
  16. attr_reader :id
  17. attr_reader :source
  18. attr_reader :destination
  19. attr_reader :branch
  20. attr_reader :title
  21. def initialize(jsonHash, options)
  22. @options = options
  23. @id = jsonHash["id"]
  24. @source = " "*12
  25. @destination = " "*12
  26. @branch = ""
  27. @title = ""
  28. source = jsonHash["source"]["commit"]
  29. destination = jsonHash["destination"]["commit"]
  30. branch = jsonHash["source"]["branch"]
  31. title = jsonHash["title"]
  32. @source = source["hash"] if !source.nil?
  33. @destination = destination["hash"] if !destination.nil?
  34. @branch = branch["name"] if !branch.nil?
  35. @title = title if !title.nil?
  36. end
  37. def to_s
  38. title = ""
  39. title += "\n" + @title + "\n" if @options["title"]
  40. title +
  41. @id.to_s.rjust(5, ' ') + " " +
  42. @source + " " +
  43. @destination + " " +
  44. @branch + "\n"
  45. end
  46. end
  47. # constructor
  48. def initialize options
  49. @url_api_prefix = 'https://bitbucket.org/api/2.0/repositories'
  50. @options = options
  51. # Try to identify hg repository
  52. hg_paths = `hg paths | grep bitbucket | head -1`
  53. if hg_paths.include? 'bitbucket.org'
  54. @repository = hg_paths.sub( %r{.*bitbucket.org/}, '').chomp
  55. else
  56. puts "Could not identify a bitbucket repository"
  57. exit
  58. end
  59. @url_prefix = @url_api_prefix + '/' + @repository
  60. @url_pullrequests = @url_prefix + "/pullrequests"
  61. end
  62. # helpers for RestClient.get calls
  63. def getUrl(url)
  64. puts url if @options["show-url"]
  65. RestClient.get(url)
  66. end
  67. def getJson(url)
  68. json = JSON.parse(getUrl(url).body)
  69. if @options["verbose"]
  70. puts JSON.pretty_generate(json)
  71. end
  72. json
  73. end
  74. # summary of open pull requests
  75. def listPullRequests()
  76. jsonHash = getJson(@url_pullrequests + "/?state=OPEN")
  77. output = ""
  78. jsonHash["values"].each { |pr| output += Summary.new(pr, @options).to_s }
  79. while jsonHash.has_key? "next"
  80. jsonHash = getJson(jsonHash["next"])
  81. jsonHash["values"].each { |pr| output += Summary.new(pr, @options).to_s }
  82. end
  83. return output
  84. end
  85. # summary of one pull request
  86. def getPullRequestSummary(id)
  87. jsonHash = getJson(@url_pullrequests + "/" + id.to_s)
  88. return Summary.new(jsonHash, @options)
  89. end
  90. # diff of pull request
  91. def getPullRequestDiff(id)
  92. response = getUrl(@url_pullrequests + "/" + id.to_s + "/diff")
  93. puts response if @options["verbose"]
  94. return response
  95. end
  96. # list of files changed by pull request
  97. def getPullRequestFiles(id)
  98. files = []
  99. diff = getPullRequestDiff(id)
  100. diff.lines.map(&:chomp).each do |line|
  101. if line.start_with? '+++ b/'
  102. line["+++ b/"] = ""
  103. files << line
  104. end
  105. end
  106. return files
  107. end
  108. # get ids for open pull requests
  109. def getOpenPullRequests()
  110. jsonHash = getJson(@url_pullrequests + "/?state=OPEN")
  111. ids = []
  112. jsonHash["values"].each { |pr| ids << pr["id"].to_i }
  113. while jsonHash.has_key? "next"
  114. jsonHash = getJson(jsonHash["next"])
  115. jsonHash["values"].each { |pr| ids << pr["id"].to_i }
  116. end
  117. return ids
  118. end
  119. # check changed files in pull request by id
  120. def checkPullRequest(id, fork=true)
  121. summary = getPullRequestSummary(id)
  122. puts "checking pull request #{id}, branch #{summary.branch}"
  123. hg_root = `hg root`.chomp
  124. `hg log -r #{summary.destination} 2>&1`
  125. if $? != 0
  126. puts "Unknown revision #{summary.destination}, try: hg pull"
  127. return
  128. end
  129. `hg log -r #{summary.source} 2>&1`
  130. if $? != 0
  131. puts "Unknown revision #{summary.source}, try: hg pull " +
  132. "(it could also be a fork)"
  133. return
  134. end
  135. ancestor=`hg log -r "ancestor(#{summary.source},#{summary.destination})" | head -1 | sed -e 's@.*:@@'`.chomp
  136. if ancestor != summary.destination
  137. puts "Need to merge branch #{summary.branch} with #{summary.destination}"
  138. end
  139. #files = getPullRequestFiles(id)
  140. #files_list = ""
  141. #files.each { |f| files_list += " " + f }
  142. #if fork
  143. # # this will allow real-time console output
  144. # exec "echo #{files_list} | sh #{hg_root}/tools/code_check.sh --quick #{summary.source}"
  145. #else
  146. # puts `echo #{files_list} | sh "#{hg_root}"/tools/code_check.sh --quick #{summary.source}`
  147. #end
  148. end
  149. end
  150. # default options
  151. options = {}
  152. options["list"] = false
  153. options["summary"] = nil
  154. options["check"] = false
  155. options["check_id"] = nil
  156. options["diff"] = nil
  157. options["files"] = nil
  158. options["show-url"] = false
  159. options["title"] = false
  160. options["verbose"] = false
  161. opt_parser = OptionParser.new do |o|
  162. o.on("-l", "--list",
  163. "List open pull requests with fields:\n" + " "*37 +
  164. "[id] [source] [dest] [branch]") { |o| options["list"] = o }
  165. o.on("-c", "--check [id]", Integer,
  166. "") { |o| options["check_id"] = o; options["check"] = true }
  167. o.on("-d", "--diff [id]", Integer,
  168. "Show diff from pull request") { |o| options["diff"] = o }
  169. o.on("-f", "--files [id]", Integer,
  170. "Show changed files in a pull request") { |o| options["files"] = o }
  171. o.on("-s", "--summary [id]", Integer,
  172. "Summarize a pull request with fields:\n" + " "*37 +
  173. "[id] [source] [dest] [branch]") { |o| options["summary"] = o }
  174. o.on("-t", "--title",
  175. "Show pull request title") { |o| options["title"] = o }
  176. o.on("-u", "--show-url",
  177. "Show urls accessed") { |o| options["show-url"] = o }
  178. o.on("-v", "--verbose",
  179. "Verbose output") { |o| options["verbose"] = o }
  180. o.on("-h", "--help", "Display this help message") do
  181. puts opt_parser
  182. exit
  183. end
  184. end
  185. opt_parser.parse!
  186. client = BitbucketTools.new(options)
  187. if options["list"]
  188. puts client.listPullRequests()
  189. elsif !options["summary"].nil?
  190. puts client.getPullRequestSummary(options["summary"])
  191. elsif !options["diff"].nil?
  192. puts client.getPullRequestDiff(options["diff"])
  193. elsif !options["files"].nil?
  194. puts client.getPullRequestFiles(options["files"])
  195. elsif options["check"]
  196. if options["check_id"].nil?
  197. # check all open pull requests
  198. client.getOpenPullRequests().each { |id|
  199. client.checkPullRequest(id, false)
  200. }
  201. else
  202. client.checkPullRequest(options["check_id"])
  203. end
  204. else
  205. puts opt_parser
  206. end