def testChangeInfoMembers(self): self.mox.ReplayAll() members = [ 'CloseIssue', 'Delete', 'Exists', 'GetFiles', 'GetFileNames', 'GetLocalRoot', 'GetIssueDescription', 'Load', 'MissingTests', 'NeedsUpload', 'PrimeLint', 'RpcServer', 'Save', 'SendToRietveld', 'SEPARATOR', 'UpdateRietveldDescription', 'description', 'issue', 'name', 'needs_upload', 'patch', 'patchset', 'reviewers', 'rietveld', ] # If this test fails, you should add the relevant test. self.compareMembers( gcl.ChangeInfo('', 0, 0, '', None, self.fake_root_dir, 'foo', False), members)
def testNormal(self): change_info = gcl.ChangeInfo('naame', 0, 0, 'deescription', [('A', 'aa'), ('M', 'bb')], self.fake_root_dir) self.mox.StubOutWithMock(change_info, 'Save') args = ['--no_watchlists'] change_info.Save() gcl.DoPresubmitChecks(change_info, False, True).AndReturn(True) gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server') gcl.tempfile.mkstemp(text=True).AndReturn((42, 'descfile')) gcl.os.write(42, change_info.description) gcl.os.close(42) gcl.GetCodeReviewSetting('CC_LIST') gcl.os.getcwd().AndReturn('somewhere') gcl.os.chdir(change_info.GetLocalRoot()) gcl.GenerateDiff(change_info.GetFileNames()) gcl.upload.RealMain([ 'upload.py', '-y', '--server=my_server', "--description_file=descfile", "--message=deescription" ], change_info.patch).AndReturn(("1", "2")) gcl.os.remove('descfile') gcl.SendToRietveld("/lint/issue%s_%s" % ('1', '2'), timeout=0.5) gcl.GetCodeReviewSetting('TRY_ON_UPLOAD').AndReturn('True') gcl.TryChange(change_info, [], swallow_exception=True) gcl.os.chdir('somewhere') self.mox.ReplayAll() gcl.UploadCL(change_info, args) self.assertEquals(change_info.issue, 1) self.assertEquals(change_info.patchset, 2)
def testSaveEmpty(self): gcl.GetChangelistInfoFile('').AndReturn('foo') gcl.WriteFile('foo', gcl.ChangeInfo._SEPARATOR.join(['0, 0, clean', '', ''])) self.mox.ReplayAll() change_info = gcl.ChangeInfo('', 0, 0, '', None, self.fake_root_dir) change_info.Save()
def testSaveDirty(self): gcl.GetChangelistInfoFile('n').AndReturn('foo') values = { 'description': 'des', 'patchset': 0, 'issue': 0, 'files': [], 'needs_upload': True, 'rietveld': 'https://foo'} gcl.gclient_utils.FileWrite( 'foo', gcl.json.dumps(values, sort_keys=True, indent=2)) self.mox.ReplayAll() change_info = gcl.ChangeInfo('n', 0, 0, 'des', None, self.fake_root_dir, 'foo', needs_upload=True) change_info.Save()
def testChangeInfoBase(self): files = [('M', 'foo'), ('A', 'bar')] self.mox.ReplayAll() o = gcl.ChangeInfo('name2', '42', '53', 'description2', files, self.fake_root_dir, 'foo', False) self.assertEquals(o.name, 'name2') self.assertEquals(o.issue, 42) self.assertEquals(o.patchset, 53) self.assertEquals(o.description, 'description2') self.assertEquals(o.patch, None) self.assertEquals(o.GetFileNames(), ['foo', 'bar']) self.assertEquals(o.GetFiles(), files) self.assertEquals(o.GetLocalRoot(), self.fake_root_dir)
def testSaveDirty(self): gcl.GetChangelistInfoFile('').AndReturn('foo') gcl.WriteFile('foo', gcl.ChangeInfo._SEPARATOR.join(['0, 0, dirty', '', ''])) self.mox.ReplayAll() change_info = gcl.ChangeInfo('', 0, 0, '', None, self.fake_root_dir, needs_upload=True) change_info.Save()
def testNormal(self): change_info = gcl.ChangeInfo( 'naame', 0, 0, 'deescription', [('A', 'aa'), ('M', 'bb')], self.fake_root_dir, 'my_server', False) self.mox.StubOutWithMock(change_info, 'Save') change_info.Save() output = presubmit_support.PresubmitOutput() gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output) gcl.tempfile.mkstemp(text=True).AndReturn((42, 'descfile')) gcl.os.write(42, change_info.description) gcl.os.close(42) gcl.GetCodeReviewSetting('CC_LIST') gcl.GetCodeReviewSetting('PRIVATE') gcl.GetCodeReviewSetting('PROJECT') gcl.os.getcwd().AndReturn('somewhere') gcl.os.chdir(change_info.GetLocalRoot()) gcl.GenerateDiff(change_info.GetFileNames()) gcl.upload.RealMain( ['upload.py', '-y', '--server=https://my_server', "--file=descfile" ], change_info.patch).AndReturn(("1", "2")) gcl.os.remove('descfile') change_info.SendToRietveld("/lint/issue%s_%s" % ('1', '2'), timeout=60) gcl.os.chdir('somewhere') gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to" " submit a try. ***") gcl.sys.stdout.write("\n") gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir) gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True ).AndReturn(change_info) self.mox.ReplayAll() gcl.CMDupload(['naame', '--no_watchlists']) self.assertEquals(change_info.issue, 1) self.assertEquals(change_info.patchset, 2) self.checkstdout('*** Upload does not submit a try; use gcl try to submit ' 'a try. ***\n' '*** Upload does not submit a try; use gcl try to submit a try. ***\n')
def testChangeInfoMembers(self): self.mox.ReplayAll() members = [ 'CloseIssue', 'Delete', 'GetFiles', 'GetFileNames', 'GetLocalRoot', 'Exists', 'Load', 'MissingTests', 'NeedsUpload', 'Save', 'UpdateRietveldDescription', 'description', 'issue', 'name', 'needs_upload', 'patch', 'patchset', ] # If this test fails, you should add the relevant test. self.compareMembers( gcl.ChangeInfo('', 0, 0, '', None, self.fake_root_dir), members)
def Revert(revisions, force=False, commit=True, send_email=True, message=None, reviewers=None): """Reverts many revisions in one change list. If force is True, it will override local modifications. If commit is True, a commit is done after the revert. If send_mail is True, a review email is sent. If message is True, it is used as the change description. reviewers overrides the blames email addresses for review email.""" # Use the oldest revision as the primary revision. changename = "revert%d" % revisions[len(revisions) - 1] if not force and os.path.exists(gcl.GetChangelistInfoFile(changename)): print "Error, change %s already exist." % changename return 1 # Move to the repository root and make the revision numbers sorted in # decreasing order. local_root = gcl.GetRepositoryRoot() os.chdir(local_root) revisions.sort(reverse=True) revisions_string = ",".join([str(rev) for rev in revisions]) revisions_string_rev = ",".join([str(-rev) for rev in revisions]) # Get all the modified files by the revision. We'll use this list to optimize # the svn merge. logs = [] for revision in revisions: logs.extend(CaptureSVNLog(["-r", str(revision), "-v"])) files = [] blames = [] repo_base = GetRepoBase() for log in logs: for file in log['paths']: file_name = file['path'] # Remove the /trunk/src/ part. The + 1 is for the last slash. if not file_name.startswith(repo_base): raise OutsideOfCheckout(file_name) files.append(file_name[len(repo_base):]) blames.append(log['author']) # On Windows, we need to fix the slashes once they got the url part removed. if sys.platform == 'win32': # On Windows, gcl expect the correct slashes. files = [file.replace('/', os.sep) for file in files] # Keep unique. files = UniqueFast(files) blames = UniqueFast(blames) if not reviewers: reviewers = blames else: reviewers = UniqueFast(reviewers) # Make sure there's something to revert. if not files: raise NoModifiedFile if not reviewers: raise NoBlameList if blames: print "Blaming %s\n" % ",".join(blames) if reviewers != blames: print "Emailing %s\n" % ",".join(reviewers) print "These files were modified in %s:" % revisions_string print "\n".join(files) print "" # Make sure these files are unmodified with svn status. status = gclient_scm.scm.SVN.CaptureStatus(files) if status: if force: # TODO(maruel): Use the tool to correctly revert '?' files. gcl.RunShell(["svn", "revert"] + files) else: raise ModifiedFile(status) # svn up on each of these files gcl.RunShell(["svn", "up"] + files) files_status = {} # Extract the first level subpaths. Subversion seems to degrade # exponentially w.r.t. repository size during merges. Working at the root # directory is too rough for svn due to the repository size. roots = UniqueFast([file.split(os.sep)[0] for file in files]) for root in roots: # Is it a subdirectory or a files? is_root_subdir = os.path.isdir(root) need_to_update = False if is_root_subdir: os.chdir(root) file_list = [] # List the file directly since it is faster when there is only one file. for file in files: if file.startswith(root): file_list.append(file[len(root) + 1:]) if len(file_list) > 1: # Listing multiple files is not supported by svn merge. file_list = ['.'] need_to_update = True else: # Oops, root was in fact a file in the root directory. file_list = [root] root = "." print "Reverting %s in %s/" % (revisions_string, root) if need_to_update: # Make sure '.' revision is high enough otherwise merge will be # unhappy. retcode = gcl.RunShellWithReturnCode(['svn', 'up', '.', '-N'])[1] if retcode: print 'svn up . -N failed in %s/.' % root return retcode command = ["svn", "merge", "-c", revisions_string_rev] command.extend(file_list) (output, retcode) = gcl.RunShellWithReturnCode(command, print_output=True) if retcode: print "'%s' failed:" % command return retcode # Grab the status lines = output.split('\n') for line in lines: if line.startswith('---'): continue if line.startswith('Skipped'): print "" raise ModifiedFile(line[9:-1]) # Update the status. status = line[:5] + ' ' file = line[5:] if is_root_subdir: files_status[root + os.sep + file] = status else: files_status[file] = status if is_root_subdir: os.chdir('..') # Transform files_status from a dictionary to a list of tuple. files_status = [(files_status[file], file) for file in files] description = "Reverting %s." % revisions_string if message: description += "\n\n" description += message # Don't use gcl.Change() since it prompts the user for infos. change_info = gcl.ChangeInfo(changename, 0, 0, description, files_status, local_root) change_info.Save() upload_args = ['--no_presubmit', '-r', ",".join(reviewers)] if send_email: upload_args.append('--send_mail') if commit: upload_args.append('--no_try') gcl.UploadCL(change_info, upload_args) retcode = 0 if commit: gcl.Commit(change_info, ['--no_presubmit', '--force']) # TODO(maruel): gclient sync (to leave the local checkout in an usable # state) retcode = gclient.Main(["gclient.py", "sync"]) return retcode