summaryrefslogtreecommitdiffstats
path: root/subcmds/download.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/download.py')
-rw-r--r--subcmds/download.py80
1 files changed, 63 insertions, 17 deletions
diff --git a/subcmds/download.py b/subcmds/download.py
index f746bc23..523f25e0 100644
--- a/subcmds/download.py
+++ b/subcmds/download.py
@@ -1,5 +1,3 @@
1# -*- coding:utf-8 -*-
2#
3# Copyright (C) 2008 The Android Open Source Project 1# Copyright (C) 2008 The Android Open Source Project
4# 2#
5# Licensed under the Apache License, Version 2.0 (the "License"); 3# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,17 +12,17 @@
14# See the License for the specific language governing permissions and 12# See the License for the specific language governing permissions and
15# limitations under the License. 13# limitations under the License.
16 14
17from __future__ import print_function
18import re 15import re
19import sys 16import sys
20 17
21from command import Command 18from command import Command
22from error import GitError 19from error import GitError, NoSuchProjectError
23 20
24CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$') 21CHANGE_RE = re.compile(r'^([1-9][0-9]*)(?:[/\.-]([1-9][0-9]*))?$')
25 22
23
26class Download(Command): 24class Download(Command):
27 common = True 25 COMMON = True
28 helpSummary = "Download and checkout a change" 26 helpSummary = "Download and checkout a change"
29 helpUsage = """ 27 helpUsage = """
30%prog {[project] change[/patchset]}... 28%prog {[project] change[/patchset]}...
@@ -36,9 +34,13 @@ If no project is specified try to use current directory as a project.
36""" 34"""
37 35
38 def _Options(self, p): 36 def _Options(self, p):
37 p.add_option('-b', '--branch',
38 help='create a new branch first')
39 p.add_option('-c', '--cherry-pick', 39 p.add_option('-c', '--cherry-pick',
40 dest='cherrypick', action='store_true', 40 dest='cherrypick', action='store_true',
41 help="cherry-pick instead of checkout") 41 help="cherry-pick instead of checkout")
42 p.add_option('-x', '--record-origin', action='store_true',
43 help='pass -x when cherry-picking')
42 p.add_option('-r', '--revert', 44 p.add_option('-r', '--revert',
43 dest='revert', action='store_true', 45 dest='revert', action='store_true',
44 help="revert instead of checkout") 46 help="revert instead of checkout")
@@ -58,6 +60,7 @@ If no project is specified try to use current directory as a project.
58 if m: 60 if m:
59 if not project: 61 if not project:
60 project = self.GetProjects(".")[0] 62 project = self.GetProjects(".")[0]
63 print('Defaulting to cwd project', project.name)
61 chg_id = int(m.group(1)) 64 chg_id = int(m.group(1))
62 if m.group(2): 65 if m.group(2):
63 ps_id = int(m.group(2)) 66 ps_id = int(m.group(2))
@@ -74,9 +77,33 @@ If no project is specified try to use current directory as a project.
74 ps_id = max(int(match.group(1)), ps_id) 77 ps_id = max(int(match.group(1)), ps_id)
75 to_get.append((project, chg_id, ps_id)) 78 to_get.append((project, chg_id, ps_id))
76 else: 79 else:
77 project = self.GetProjects([a])[0] 80 projects = self.GetProjects([a])
81 if len(projects) > 1:
82 # If the cwd is one of the projects, assume they want that.
83 try:
84 project = self.GetProjects('.')[0]
85 except NoSuchProjectError:
86 project = None
87 if project not in projects:
88 print('error: %s matches too many projects; please re-run inside '
89 'the project checkout.' % (a,), file=sys.stderr)
90 for project in projects:
91 print(' %s/ @ %s' % (project.relpath, project.revisionExpr),
92 file=sys.stderr)
93 sys.exit(1)
94 else:
95 project = projects[0]
96 print('Defaulting to cwd project', project.name)
78 return to_get 97 return to_get
79 98
99 def ValidateOptions(self, opt, args):
100 if opt.record_origin:
101 if not opt.cherrypick:
102 self.OptionParser.error('-x only makes sense with --cherry-pick')
103
104 if opt.ffonly:
105 self.OptionParser.error('-x and --ff are mutually exclusive options')
106
80 def Execute(self, opt, args): 107 def Execute(self, opt, args):
81 for project, change_id, ps_id in self._ParseChangeIds(args): 108 for project, change_id, ps_id in self._ParseChangeIds(args):
82 dl = project.DownloadPatchSet(change_id, ps_id) 109 dl = project.DownloadPatchSet(change_id, ps_id)
@@ -93,22 +120,41 @@ If no project is specified try to use current directory as a project.
93 continue 120 continue
94 121
95 if len(dl.commits) > 1: 122 if len(dl.commits) > 1:
96 print('[%s] %d/%d depends on %d unmerged changes:' \ 123 print('[%s] %d/%d depends on %d unmerged changes:'
97 % (project.name, change_id, ps_id, len(dl.commits)), 124 % (project.name, change_id, ps_id, len(dl.commits)),
98 file=sys.stderr) 125 file=sys.stderr)
99 for c in dl.commits: 126 for c in dl.commits:
100 print(' %s' % (c), file=sys.stderr) 127 print(' %s' % (c), file=sys.stderr)
101 if opt.cherrypick:
102 try:
103 project._CherryPick(dl.commit)
104 except GitError:
105 print('[%s] Could not complete the cherry-pick of %s' \
106 % (project.name, dl.commit), file=sys.stderr)
107 sys.exit(1)
108 128
129 if opt.cherrypick:
130 mode = 'cherry-pick'
109 elif opt.revert: 131 elif opt.revert:
110 project._Revert(dl.commit) 132 mode = 'revert'
111 elif opt.ffonly: 133 elif opt.ffonly:
112 project._FastForward(dl.commit, ffonly=True) 134 mode = 'fast-forward merge'
113 else: 135 else:
114 project._Checkout(dl.commit) 136 mode = 'checkout'
137
138 # We'll combine the branch+checkout operation, but all the rest need a
139 # dedicated branch start.
140 if opt.branch and mode != 'checkout':
141 project.StartBranch(opt.branch)
142
143 try:
144 if opt.cherrypick:
145 project._CherryPick(dl.commit, ffonly=opt.ffonly,
146 record_origin=opt.record_origin)
147 elif opt.revert:
148 project._Revert(dl.commit)
149 elif opt.ffonly:
150 project._FastForward(dl.commit, ffonly=True)
151 else:
152 if opt.branch:
153 project.StartBranch(opt.branch, revision=dl.commit)
154 else:
155 project._Checkout(dl.commit)
156
157 except GitError:
158 print('[%s] Could not complete the %s of %s'
159 % (project.name, mode, dl.commit), file=sys.stderr)
160 sys.exit(1)