OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 """Client-side script to send a try job to the try server. It communicates to | 5 """Client-side script to send a try job to the try server. It communicates to |
6 the try server by either writting to a svn repository or by directly connecting | 6 the try server by either writting to a svn repository or by directly connecting |
7 to the server by HTTP. | 7 to the server by HTTP. |
8 """ | 8 """ |
9 | 9 |
10 import datetime | 10 import datetime |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 def __str__(self): | 67 def __str__(self): |
68 return self.args[0] + '\n' + HELP_STRING | 68 return self.args[0] + '\n' + HELP_STRING |
69 | 69 |
70 | 70 |
71 def EscapeDot(name): | 71 def EscapeDot(name): |
72 return name.replace('.', '-') | 72 return name.replace('.', '-') |
73 | 73 |
74 | 74 |
75 class SCM(object): | 75 class SCM(object): |
76 """Simplistic base class to implement one function: ProcessOptions.""" | 76 """Simplistic base class to implement one function: ProcessOptions.""" |
77 def __init__(self, options, cwd): | 77 def __init__(self, options, path): |
78 self.checkout_root = cwd | 78 items = path.split('@') |
| 79 assert len(items) <= 2 |
| 80 self.checkout_root = items[0] |
| 81 items.append(None) |
| 82 self.diff_against = items[1] |
79 self.options = options | 83 self.options = options |
80 self.files = self.options.files | 84 self.files = self.options.files |
81 self.options.files = None | 85 self.options.files = None |
82 self.codereview_settings = None | 86 self.codereview_settings = None |
83 self.codereview_settings_file = 'codereview.settings' | 87 self.codereview_settings_file = 'codereview.settings' |
84 | 88 |
85 def GetFileNames(self): | 89 def GetFileNames(self): |
86 """Return the list of files in the diff.""" | 90 """Return the list of files in the diff.""" |
87 return self.files | 91 return self.files |
88 | 92 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 """ | 173 """ |
170 if not self.files: | 174 if not self.files: |
171 previous_cwd = os.getcwd() | 175 previous_cwd = os.getcwd() |
172 os.chdir(self.checkout_root) | 176 os.chdir(self.checkout_root) |
173 excluded = ['!', '?', 'X', ' ', '~'] | 177 excluded = ['!', '?', 'X', ' ', '~'] |
174 self.files = [ | 178 self.files = [ |
175 f[1] for f in scm.SVN.CaptureStatus(self.checkout_root) | 179 f[1] for f in scm.SVN.CaptureStatus(self.checkout_root) |
176 if f[0][0] not in excluded | 180 if f[0][0] not in excluded |
177 ] | 181 ] |
178 os.chdir(previous_cwd) | 182 os.chdir(previous_cwd) |
179 return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True) | 183 return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True, |
| 184 revision=self.diff_against) |
180 | 185 |
181 | 186 |
182 class GIT(SCM): | 187 class GIT(SCM): |
183 """Gathers the options and diff for a git checkout.""" | 188 """Gathers the options and diff for a git checkout.""" |
184 def __init__(self, *args, **kwargs): | 189 def __init__(self, *args, **kwargs): |
185 SCM.__init__(self, *args, **kwargs) | 190 SCM.__init__(self, *args, **kwargs) |
186 self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root) | 191 self.checkout_root = scm.GIT.GetCheckoutRoot(self.checkout_root) |
187 if not self.options.name: | 192 if not self.options.name: |
188 self.options.name = scm.GIT.GetPatchName(self.checkout_root) | 193 self.options.name = scm.GIT.GetPatchName(self.checkout_root) |
189 if not self.options.email: | 194 if not self.options.email: |
190 self.options.email = scm.GIT.GetEmail(self.checkout_root) | 195 self.options.email = scm.GIT.GetEmail(self.checkout_root) |
191 logging.info("GIT(%s)" % self.checkout_root) | 196 logging.info("GIT(%s)" % self.checkout_root) |
192 | 197 |
193 def ReadRootFile(self, filename): | 198 def ReadRootFile(self, filename): |
194 try: | 199 try: |
195 # A git checkout is always a full checkout. | 200 # A git checkout is always a full checkout. |
196 data = gclient_utils.FileRead(os.path.join(self.checkout_root, filename)) | 201 data = gclient_utils.FileRead(os.path.join(self.checkout_root, filename)) |
197 logging.debug('%s:\n%s' % (filename, data)) | 202 logging.debug('%s:\n%s' % (filename, data)) |
198 return data | 203 return data |
199 except (IOError, OSError): | 204 except (IOError, OSError): |
200 logging.debug('%s:\nNone' % filename) | 205 logging.debug('%s:\nNone' % filename) |
201 return None | 206 return None |
202 | 207 |
203 def GenerateDiff(self): | 208 def GenerateDiff(self): |
204 # For now, ignores self.files | 209 # For now, ignores self.files |
205 return scm.GIT.GenerateDiff(self.checkout_root, full_move=True) | 210 return scm.GIT.GenerateDiff(self.checkout_root, full_move=True, |
| 211 branch=self.diff_against) |
206 | 212 |
207 | 213 |
208 def _ParseSendChangeOptions(options): | 214 def _ParseSendChangeOptions(options): |
209 """Parse common options passed to _SendChangeHTTP and _SendChangeSVN.""" | 215 """Parse common options passed to _SendChangeHTTP and _SendChangeSVN.""" |
210 values = {} | 216 values = {} |
211 if options.email: | 217 if options.email: |
212 values['email'] = options.email | 218 values['email'] = options.email |
213 values['user'] = options.user | 219 values['user'] = options.user |
214 values['name'] = options.name | 220 values['name'] = options.name |
215 if options.bot: | 221 if options.bot: |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 support it yet. | 364 support it yet. |
359 | 365 |
360 This examines the path directory, guesses which SCM we're using, and | 366 This examines the path directory, guesses which SCM we're using, and |
361 returns an instance of the appropriate class. Exit with an error if we can't | 367 returns an instance of the appropriate class. Exit with an error if we can't |
362 figure it out. | 368 figure it out. |
363 | 369 |
364 Returns: | 370 Returns: |
365 A SCM instance. Exits if the SCM can't be guessed. | 371 A SCM instance. Exits if the SCM can't be guessed. |
366 """ | 372 """ |
367 __pychecker__ = 'no-returnvalues' | 373 __pychecker__ = 'no-returnvalues' |
| 374 real_path = path.split('@')[0] |
368 logging.info("GuessVCS(%s)" % path) | 375 logging.info("GuessVCS(%s)" % path) |
369 # Subversion has a .svn in all working directories. | 376 # Subversion has a .svn in all working directories. |
370 if os.path.isdir(os.path.join(path, '.svn')): | 377 if os.path.isdir(os.path.join(real_path, '.svn')): |
371 return SVN(options, path) | 378 return SVN(options, path) |
372 | 379 |
373 # Git has a command to test if you're in a git tree. | 380 # Git has a command to test if you're in a git tree. |
374 # Try running it, but don't die if we don't have git installed. | 381 # Try running it, but don't die if we don't have git installed. |
375 try: | 382 try: |
376 gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"], | 383 gclient_utils.CheckCall(["git", "rev-parse", "--is-inside-work-tree"], |
377 path) | 384 real_path) |
378 return GIT(options, path) | 385 return GIT(options, path) |
379 except gclient_utils.CheckCallError, e: | 386 except gclient_utils.CheckCallError, e: |
380 if e.retcode != errno.ENOENT and e.retcode != 128: | 387 if e.retcode != errno.ENOENT and e.retcode != 128: |
381 # ENOENT == 2 = they don't have git installed. | 388 # ENOENT == 2 = they don't have git installed. |
382 # 128 = git error code when not in a repo. | 389 # 128 = git error code when not in a repo. |
383 logging.warn(e.retcode) | 390 logging.warn(e.retcode) |
384 raise | 391 raise |
385 raise NoTryServerAccess("Could not guess version control system. " | 392 raise NoTryServerAccess("Could not guess version control system. " |
386 "Are you in a working copy directory?") | 393 "Are you in a working copy directory?") |
387 | 394 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 help="File containing the diff to try") | 464 help="File containing the diff to try") |
458 group.add_option("--url", | 465 group.add_option("--url", |
459 help="Url where to grab a patch") | 466 help="Url where to grab a patch") |
460 group.add_option("--root", | 467 group.add_option("--root", |
461 help="Root to use for the patch; base subdirectory for " | 468 help="Root to use for the patch; base subdirectory for " |
462 "patch created in a subdirectory") | 469 "patch created in a subdirectory") |
463 group.add_option("-p", "--patchlevel", type='int', metavar="LEVEL", | 470 group.add_option("-p", "--patchlevel", type='int', metavar="LEVEL", |
464 help="Used as -pN parameter to patch") | 471 help="Used as -pN parameter to patch") |
465 group.add_option("-s", "--sub_rep", action="append", default=[], | 472 group.add_option("-s", "--sub_rep", action="append", default=[], |
466 help="Subcheckout to use in addition. This is mainly " | 473 help="Subcheckout to use in addition. This is mainly " |
467 "useful for gclient-style checkouts.") | 474 "useful for gclient-style checkouts. Use @rev or " |
| 475 "@branch or @branch1..branch2 to specify the " |
| 476 "revision/branch to diff against.") |
468 group.add_option("--no_gclient", action="store_true", | 477 group.add_option("--no_gclient", action="store_true", |
469 help="Disable automatic search for gclient checkout.") | 478 help="Disable automatic search for gclient checkout.") |
470 parser.add_option_group(group) | 479 parser.add_option_group(group) |
471 | 480 |
472 group = optparse.OptionGroup(parser, "Access the try server by HTTP") | 481 group = optparse.OptionGroup(parser, "Access the try server by HTTP") |
473 group.add_option("--use_http", | 482 group.add_option("--use_http", |
474 action="store_const", | 483 action="store_const", |
475 const=_SendChangeHTTP, | 484 const=_SendChangeHTTP, |
476 dest="send_patch", | 485 dest="send_patch", |
477 help="Use HTTP to talk to the try server [default]") | 486 help="Use HTTP to talk to the try server [default]") |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 except (InvalidScript, NoTryServerAccess), e: | 611 except (InvalidScript, NoTryServerAccess), e: |
603 if swallow_exception: | 612 if swallow_exception: |
604 return 1 | 613 return 1 |
605 print e | 614 print e |
606 return 1 | 615 return 1 |
607 return 0 | 616 return 0 |
608 | 617 |
609 | 618 |
610 if __name__ == "__main__": | 619 if __name__ == "__main__": |
611 sys.exit(TryChange(None, [], False)) | 620 sys.exit(TryChange(None, [], False)) |
OLD | NEW |