Chromium Code Reviews| Index: trychange.py | 
| =================================================================== | 
| --- trychange.py (revision 102922) | 
| +++ trychange.py (working copy) | 
| @@ -100,7 +100,12 @@ | 
| items.append(None) | 
| self.diff_against = items[1] | 
| self.options = options | 
| - self.files = self.options.files | 
| + # Lazy-load file list from the SCM unless files were specified in options. | 
| + self._files = None | 
| + self._file_tuples = None | 
| + if self.options.files: | 
| + self._files = self.options.files | 
| + self._file_tuples = [('M', f) for f in self.files] | 
| self.options.files = None | 
| self.codereview_settings = None | 
| self.codereview_settings_file = 'codereview.settings' | 
| @@ -187,7 +192,39 @@ | 
| logging.warning('Didn\'t find %s' % filename) | 
| return None | 
| + def _SetFileTuples(self, file_tuples): | 
| + excluded = ['!', '?', 'X', ' ', '~'] | 
| + def Excluded(f): | 
| + if f[0][0] in excluded: | 
| + return True | 
| + for r in self.options.exclude: | 
| + if re.search(r, f[1]): | 
| + logging.info('Ignoring "%s"' % f[1]) | 
| + return True | 
| + return False | 
| + self._file_tuples = [f for f in file_tuples if not Excluded(f)] | 
| + self._files = [f[1] for f in self._file_tuples] | 
| + | 
| + def CaptureStatus(self): | 
| + """Returns the 'svn status' emulated output as an array of (status, file) | 
| + tuples.""" | 
| + raise NotImplementedError( | 
| + "abstract method -- subclass %s must override" % self.__class__) | 
| + | 
| + @property | 
| + def files(self): | 
| + if self._files is None: | 
| + self._SetFileTuples(self.CaptureStatus()) | 
| + return self._files | 
| + | 
| + @property | 
| + def file_tuples(self): | 
| + if self._file_tuples is None: | 
| + self._SetFileTuples(self.CaptureStatus()) | 
| + return self._file_tuples | 
| + | 
| + | 
| class SVN(SCM): | 
| """Gathers the options and diff for a subversion checkout.""" | 
| def __init__(self, *args, **kwargs): | 
| @@ -210,29 +247,19 @@ | 
| logging.debug('%s:\n%s' % (filename, data)) | 
| return data | 
| + def CaptureStatus(self): | 
| + previous_cwd = os.getcwd() | 
| + os.chdir(self.checkout_root) | 
| + result = scm.SVN.CaptureStatus(self.checkout_root) | 
| + os.chdir(previous_cwd) | 
| + return result | 
| + | 
| def GenerateDiff(self): | 
| """Returns a string containing the diff for the given file list. | 
| The files in the list should either be absolute paths or relative to the | 
| given root. | 
| """ | 
| - if not self.files: | 
| - previous_cwd = os.getcwd() | 
| - os.chdir(self.checkout_root) | 
| - | 
| - excluded = ['!', '?', 'X', ' ', '~'] | 
| - def Excluded(f): | 
| - if f[0][0] in excluded: | 
| - return True | 
| - for r in self.options.exclude: | 
| - if re.search(r, f[1]): | 
| - logging.info('Ignoring "%s"' % f[1]) | 
| - return True | 
| - return False | 
| - | 
| - self.files = [f[1] for f in scm.SVN.CaptureStatus(self.checkout_root) | 
| - if not Excluded(f)] | 
| - os.chdir(previous_cwd) | 
| return scm.SVN.GenerateDiff(self.files, self.checkout_root, full_move=True, | 
| revision=self.diff_against) | 
| @@ -255,19 +282,10 @@ | 
| "(via the --track argument to \"git checkout -b ...\"") | 
| logging.info("GIT(%s)" % self.checkout_root) | 
| + def CaptureStatus(self): | 
| + return scm.GIT.CaptureStatus(self.checkout_root, self.diff_against) | 
| + | 
| def GenerateDiff(self): | 
| - if not self.files: | 
| - self.files = scm.GIT.GetDifferentFiles(self.checkout_root, | 
| - branch=self.diff_against) | 
| - | 
| - def NotExcluded(f): | 
| - for r in self.options.exclude: | 
| - if re.search(r, f): | 
| - logging.info('Ignoring "%s"' % f) | 
| - return False | 
| - return True | 
| - | 
| - self.files = filter(NotExcluded, self.files) | 
| return scm.GIT.GenerateDiff(self.checkout_root, files=self.files, | 
| full_move=True, | 
| branch=self.diff_against) | 
| @@ -456,14 +474,17 @@ | 
| def GetMungedDiff(path_diff, diff): | 
| # Munge paths to match svn. | 
| + changed_files = [] | 
| for i in range(len(diff)): | 
| if diff[i].startswith('--- ') or diff[i].startswith('+++ '): | 
| new_file = posixpath.join(path_diff, diff[i][4:]).replace('\\', '/') | 
| + changed_files.append(('M', new_file.split('\t')[0])) | 
| diff[i] = diff[i][0:4] + new_file | 
| - return diff | 
| + return (diff, changed_files) | 
| def TryChange(argv, | 
| + change, | 
| file_list, | 
| 
 
M-A Ruel
2011/09/30 15:38:44
I just realized this was an error. TryChange shoul
 
 | 
| swallow_exception, | 
| prog=None, | 
| @@ -646,6 +667,7 @@ | 
| options.rietveld_url = match.group(1) | 
| try: | 
| + changed_files = None | 
| # Always include os.getcwd() in the checkout settings. | 
| checkouts = [] | 
| path = os.getcwd() | 
| @@ -689,7 +711,8 @@ | 
| diff_url = ('%s/download/issue%d_%d.diff' % | 
| (options.rietveld_url, options.issue, options.patchset)) | 
| diff = GetMungedDiff('', urllib.urlopen(diff_url).readlines()) | 
| - options.diff = ''.join(diff) | 
| + options.diff = ''.join(diff[0]) | 
| + changed_files = diff[1] | 
| else: | 
| # Use this as the base. | 
| root = checkouts[0].checkout_root | 
| @@ -698,9 +721,21 @@ | 
| diff = checkout.GenerateDiff().splitlines(True) | 
| path_diff = gclient_utils.PathDifference(root, checkout.checkout_root) | 
| # Munge it. | 
| - diffs.extend(GetMungedDiff(path_diff, diff)) | 
| + diffs.extend(GetMungedDiff(path_diff, diff)[0]) | 
| options.diff = ''.join(diffs) | 
| + if not options.name: | 
| + if options.issue: | 
| + options.name = 'Issue %s' % options.issue | 
| + else: | 
| + options.name = 'Unnamed' | 
| + print('Note: use --name NAME to change the try job name.') | 
| + | 
| + if not options.email: | 
| + parser.error('Using an anonymous checkout. Please use --email or set ' | 
| + 'the TRYBOT_RESULTS_EMAIL_ADDRESS environment variable.') | 
| + print('Results will be emailed to: ' + options.email) | 
| + | 
| if not options.bot: | 
| # Get try slaves from PRESUBMIT.py files if not specified. | 
| # Even if the diff comes from options.url, use the local checkout for bot | 
| @@ -708,7 +743,18 @@ | 
| try: | 
| import presubmit_support | 
| root_presubmit = checkouts[0].ReadRootFile('PRESUBMIT.py') | 
| + if not change: | 
| + if not changed_files: | 
| + changed_files = checkouts[0].file_tuples | 
| + change = presubmit_support.Change(options.name, | 
| + '', | 
| + checkouts[0].checkout_root, | 
| + changed_files, | 
| + options.issue, | 
| + options.patchset, | 
| + options.email) | 
| options.bot = presubmit_support.DoGetTrySlaves( | 
| + change, | 
| checkouts[0].GetFileNames(), | 
| checkouts[0].checkout_root, | 
| root_presubmit, | 
| @@ -720,18 +766,6 @@ | 
| # If no bot is specified, either the default pool will be selected or the | 
| # try server will refuse the job. Either case we don't need to interfere. | 
| - if options.name is None: | 
| - if options.issue: | 
| - options.name = 'Issue %s' % options.issue | 
| - else: | 
| - options.name = 'Unnamed' | 
| - print('Note: use --name NAME to change the try job name.') | 
| - if not options.email: | 
| - parser.error('Using an anonymous checkout. Please use --email or set ' | 
| - 'the TRYBOT_RESULTS_EMAIL_ADDRESS environment variable.') | 
| - else: | 
| - print('Results will be emailed to: ' + options.email) | 
| - | 
| # Prevent rietveld updates if we aren't running all the tests. | 
| if options.testfilter is not None: | 
| options.issue = None | 
| @@ -767,4 +801,4 @@ | 
| if __name__ == "__main__": | 
| fix_encoding.fix_encoding() | 
| - sys.exit(TryChange(None, [], False)) | 
| + sys.exit(TryChange(None, None, [], False)) |