Index: drover.py |
=================================================================== |
--- drover.py (revision 109710) |
+++ drover.py (working copy) |
@@ -6,7 +6,9 @@ |
import optparse |
import os |
import re |
+import string |
import sys |
+import urllib2 |
import breakpad # pylint: disable=W0611 |
@@ -25,6 +27,10 @@ |
--merge <revision> --branch <branch_num> |
Example: %(app)s --merge 12345 --branch 187 |
+[Merge from trunk to milestone] |
+--merge <revision> --milestone <milestone_num> |
+Example: %(app)s -- merge 12345 --milestone 16 |
+ |
[Merge from trunk to local copy] |
--merge <revision> --local |
Example: %(app)s --merge 12345 --local |
@@ -357,6 +363,64 @@ |
""" |
return ['%s/%s' % (f[2], f[3]) for f in files_info] |
+ |
+def getBranchForMilestone(milestone): |
+ """Queries omahaproxy.appspot.com for the branch number given |milestone|. |
+ """ |
+ OMAHA_PROXY_URL = "http://omahaproxy.appspot.com" |
+ request = urllib2.Request(OMAHA_PROXY_URL) |
+ try: |
+ response = urllib2.urlopen(request) |
+ except urllib2.HTTPError, e: |
+ print "Failed to query %s: %d" % (OMAHA_PROXY_URL, e.code) |
+ return None |
+ |
+ # Dictionary of [branch: major]. When searching for the appropriate branch |
+ # matching |milestone|, all major versions that match are added to the |
+ # dictionary. If all of the branches are the same, this branch value is |
+ # returned; otherwise, the user is prompted to accept the largest branch |
+ # value. |
+ branch_dict = {} |
+ |
+ # Slice the first line since it's column information text. |
+ for line in response.readlines()[1:]: |
+ # Version data is CSV. |
+ parameters = string.split(line, ',') |
+ |
+ # Version is the third parameter and consists of a quad of numbers separated |
+ # by periods. |
+ version = string.split(parameters[2], '.') |
+ major = int(version[0], 10) |
+ if major != milestone: |
+ continue |
+ |
+ # Branch number is the third value in the quad. |
+ branch_dict[version[2]] = major |
+ |
+ if not branch_dict: |
+ # |milestone| not found. |
+ print "Milestone provided is invalid" |
+ return None |
+ |
+ # The following returns a sorted list of the keys of |branch_dict|. |
+ sorted_branches = sorted(branch_dict) |
+ branch = sorted_branches[0] |
+ |
+ # If all keys match, the branch is the same for all platforms given |
+ # |milestone|. This is the safe case, so return the branch. |
+ if len(sorted_branches) == 1: |
+ return branch |
+ |
+ # Not all of the platforms have the same branch. Prompt the user and return |
+ # the greatest (by value) branch on success. |
+ if prompt("Not all platforms have the same branch number, " |
+ "continue with branch %s?" % branch): |
+ return branch |
+ |
+ # User cancelled. |
+ return None |
+ |
+ |
def prompt(question): |
while True: |
print question + " [y|n]:", |
@@ -386,6 +450,12 @@ |
SKIP_CHECK_WORKING = True |
PROMPT_FOR_AUTHOR = False |
+ # Translate a given milestone to the appropriate branch number. |
+ if options.milestone: |
+ options.branch = getBranchForMilestone(options.milestone) |
+ if not options.branch: |
+ return 1 |
+ |
DEFAULT_WORKING = "drover_" + str(revision) |
if options.branch: |
DEFAULT_WORKING += ("_" + options.branch) |
@@ -522,6 +592,8 @@ |
help='Revision to merge from trunk to branch') |
option_parser.add_option('-b', '--branch', |
help='Branch to revert or merge from') |
+ option_parser.add_option('-M', '--milestone', type="int", |
+ help='Milestone to revert or merge from') |
option_parser.add_option('-l', '--local', action='store_true', |
help='Local working copy to merge to') |
option_parser.add_option('-s', '--sbranch', |
@@ -543,14 +615,21 @@ |
option_parser.error("You need at least --merge or --revert") |
return 1 |
- if options.merge and not options.branch and not options.local: |
- option_parser.error("--merge requires either --branch or --local") |
+ if options.merge and not (options.branch or options.milestone or |
+ options.local): |
+ option_parser.error("--merge requires either --branch " |
+ "or --milestone or --local") |
return 1 |
- if options.local and (options.revert or options.branch): |
- option_parser.error("--local cannot be used with --revert or --branch") |
+ if options.local and (options.revert or options.branch or options.milestone): |
+ option_parser.error("--local cannot be used with --revert " |
+ "or --branch or --milestone") |
return 1 |
+ if options.branch and options.milestone: |
+ option_parser.error("--branch cannot be used with --milestone") |
+ return 1 |
+ |
return drover(options, args) |