blob: 9018455f3b9ba4e3f578bbce3c9b342672c2f232 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import re
17import sys
18
19from command import InteractiveCommand
20from editor import Editor
21from error import UploadError
22
23def _die(fmt, *args):
24 msg = fmt % args
25 print >>sys.stderr, 'error: %s' % msg
26 sys.exit(1)
27
28class Upload(InteractiveCommand):
29 common = True
30 helpSummary = "Upload changes for code review"
31 helpUsage="""
32%prog [<project>]...
33"""
34 helpDescription = """
35The '%prog' command is used to send changes to the Gerrit code
36review system. It searches for changes in local projects that do
37not yet exist in the corresponding remote repository. If multiple
38changes are found, '%prog' opens an editor to allow the
39user to choose which change to upload. After a successful upload,
40repo prints the URL for the change in the Gerrit code review system.
41
42'%prog' searches for uploadable changes in all projects listed
43at the command line. Projects can be specified either by name, or
44by a relative or absolute path to the project's local directory. If
45no projects are specified, '%prog' will search for uploadable
46changes in all projects listed in the manifest.
47"""
48
49 def _SingleBranch(self, branch):
50 project = branch.project
51 name = branch.name
52 date = branch.date
53 list = branch.commits
54
55 print 'Upload project %s/:' % project.relpath
56 print ' branch %s (%2d commit%s, %s):' % (
57 name,
58 len(list),
59 len(list) != 1 and 's' or '',
60 date)
61 for commit in list:
62 print ' %s' % commit
63
64 sys.stdout.write('(y/n)? ')
65 answer = sys.stdin.readline().strip()
66 if answer in ('y', 'Y', 'yes', '1', 'true', 't'):
67 self._UploadAndReport([branch])
68 else:
69 _die("upload aborted by user")
70
71 def _MultipleBranches(self, pending):
72 projects = {}
73 branches = {}
74
75 script = []
76 script.append('# Uncomment the branches to upload:')
77 for project, avail in pending:
78 script.append('#')
79 script.append('# project %s/:' % project.relpath)
80
81 b = {}
82 for branch in avail:
83 name = branch.name
84 date = branch.date
85 list = branch.commits
86
87 if b:
88 script.append('#')
89 script.append('# branch %s (%2d commit%s, %s):' % (
90 name,
91 len(list),
92 len(list) != 1 and 's' or '',
93 date))
94 for commit in list:
95 script.append('# %s' % commit)
96 b[name] = branch
97
98 projects[project.relpath] = project
99 branches[project.name] = b
100 script.append('')
101
102 script = Editor.EditString("\n".join(script)).split("\n")
103
104 project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$')
105 branch_re = re.compile(r'^\s*branch\s*([^\s(]+)\s*\(.*')
106
107 project = None
108 todo = []
109
110 for line in script:
111 m = project_re.match(line)
112 if m:
113 name = m.group(1)
114 project = projects.get(name)
115 if not project:
116 _die('project %s not available for upload', name)
117 continue
118
119 m = branch_re.match(line)
120 if m:
121 name = m.group(1)
122 if not project:
123 _die('project for branch %s not in script', name)
124 branch = branches[project.name].get(name)
125 if not branch:
126 _die('branch %s not in %s', name, project.relpath)
127 todo.append(branch)
128 if not todo:
129 _die("nothing uncommented for upload")
130 self._UploadAndReport(todo)
131
132 def _UploadAndReport(self, todo):
133 have_errors = False
134 for branch in todo:
135 try:
136 branch.UploadForReview()
137 branch.uploaded = True
138 except UploadError, e:
139 branch.error = e
140 branch.uploaded = False
141 have_errors = True
142
143 print >>sys.stderr, ''
144 print >>sys.stderr, '--------------------------------------------'
145
146 if have_errors:
147 for branch in todo:
148 if not branch.uploaded:
149 print >>sys.stderr, '[FAILED] %-15s %-15s (%s)' % (
150 branch.project.relpath + '/', \
151 branch.name, \
152 branch.error)
153 print >>sys.stderr, ''
154
155 for branch in todo:
156 if branch.uploaded:
157 print >>sys.stderr, '[OK ] %-15s %s' % (
158 branch.project.relpath + '/',
159 branch.name)
160 print >>sys.stderr, '%s' % branch.tip_url
Shawn O. Pearce0758d2f2008-10-22 13:13:40 -0700161 print >>sys.stderr, '(as %s)' % branch.owner_email
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700162 print >>sys.stderr, ''
163
164 if have_errors:
165 sys.exit(1)
166
167 def Execute(self, opt, args):
168 project_list = self.GetProjects(args)
169 pending = []
170
171 for project in project_list:
172 avail = project.GetUploadableBranches()
173 if avail:
174 pending.append((project, avail))
175
176 if not pending:
177 print >>sys.stdout, "no branches ready for upload"
178 elif len(pending) == 1 and len(pending[0][1]) == 1:
179 self._SingleBranch(pending[0][1][0])
180 else:
181 self._MultipleBranches(pending)