Example #1
0
    def testSuggestReviewers(self):
        change_info = self.fakeChange()
        output = presubmit_support.PresubmitOutput()
        output.reviewers = ['*****@*****.**', '*****@*****.**']
        gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
        #gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server')
        gcl.os.getcwd().AndReturn('somewhere')
        gcl.os.chdir('proout')
        gcl.GenerateDiff(change_info.GetFileNames())
        gcl.upload.RealMain([
            'upload.py', '-y', '--server=https://my_server',
            '[email protected],[email protected]', '--issue=1',
            '--title= '
        ], change_info.patch).AndReturn(("1", "2"))
        change_info.get_reviewers().AndReturn(
            ['[email protected],[email protected]'])
        change_info.Save()
        change_info.PrimeLint()
        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'])
        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'
        )
Example #2
0
 def mockLoad(self, files=None):
     self.mox.StubOutWithMock(gcl, 'GetRepositoryRoot')
     self.mox.StubOutWithMock(gcl.ChangeInfo, 'Load')
     gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
     change_info = self.fakeChange(files)
     gcl.ChangeInfo.Load('naame', self.fake_root_dir, True,
                         True).AndReturn(change_info)
     return change_info
Example #3
0
 def ProcessOptions(self):
     if not self.options.diff:
         # Generate the diff with svn and write it to the submit queue path.  The
         # files are relative to the repository root, but we need patches relative
         # to one level up from there (i.e., 'src'), so adjust both the file
         # paths and the root of the diff.
         source_root = GetSourceRoot()
         prefix = PathDifference(source_root, gcl.GetRepositoryRoot())
         adjusted_paths = [
             os.path.join(prefix, x) for x in self.options.files
         ]
         self.options.diff = self.GenerateDiff(adjusted_paths,
                                               root=source_root)
         self.change_info = gcl.LoadChangelistInfoForMultiple(
             self.options.name, gcl.GetRepositoryRoot(), True, True)
     if not self.options.email:
         self.options.email = scm.SVN.GetEmail(gcl.GetRepositoryRoot())
Example #4
0
 def testGetRepositoryRootGood(self):
     gcl.REPOSITORY_ROOT = None
     root_path = gcl.os.path.join('bleh', 'prout', 'pouet')
     gcl.os.getcwd().AndReturn(root_path)
     result1 = {"Repository Root": "Some root"}
     gcl.SVN.CaptureInfo(root_path, print_error=False).AndReturn(result1)
     gcl.os.getcwd().AndReturn(root_path)
     results2 = {"Repository Root": "A different root"}
     gcl.SVN.CaptureInfo(gcl.os.path.dirname(root_path),
                         print_error=False).AndReturn(results2)
     self.mox.ReplayAll()
     self.assertEquals(gcl.GetRepositoryRoot(), root_path)
Example #5
0
    def testNoServer(self):
        self.mox.StubOutWithMock(gcl.sys, 'stderr')
        gcl.sys.stderr.write(
            'Don\'t use the -s flag, fix codereview.settings instead')
        gcl.sys.stderr.write('\n')
        gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
        gcl.ChangeInfo.Load('naame', self.fake_root_dir, True,
                            True).AndReturn(1)
        self.mox.ReplayAll()

        try:
            gcl.CMDupload(['naame', '-s', 'foo'])
            self.fail()
        except SystemExit:
            pass
Example #6
0
    def GenerateDiff(self, files, root):
        """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 no root directory is provided, the repository root will be
    used.
    """
        previous_cwd = os.getcwd()
        if root is None:
            os.chdir(gcl.GetRepositoryRoot())
        else:
            os.chdir(root)

        # Directories will return None so filter them out.
        diff = filter(None, [scm.SVN.DiffItem(f) for f in files])
        os.chdir(previous_cwd)
        return "".join(diff)
Example #7
0
  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')
Example #8
0
    def testReviewersInDescription(self):
        change_info = self.mox.CreateMock(gcl.ChangeInfo)
        change_info.name = 'naame'
        change_info.issue = 1
        change_info.patchset = 0
        change_info.description = 'deescription\n\[email protected]',
        change_info.files = [('A', 'aa'), ('M', 'bb')]
        change_info.patch = None
        change_info.rietveld = 'https://my_server'
        files = [item[1] for item in change_info.files]
        output = presubmit_support.PresubmitOutput()
        gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
        #gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server')
        gcl.os.getcwd().AndReturn('somewhere')
        change_info.GetFiles().AndReturn(change_info.files)
        change_info.get_reviewers().AndReturn(['*****@*****.**'])
        change_info.GetFileNames().AndReturn(files)
        change_info.GetLocalRoot().AndReturn('proout')
        gcl.os.chdir('proout')
        gcl.GenerateDiff(files)
        gcl.upload.RealMain([
            'upload.py', '-y', '--server=https://my_server',
            '[email protected]', '--issue=1', '--title= '
        ], change_info.patch).AndReturn(("1", "2"))
        change_info.Save()
        change_info.PrimeLint()
        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'])
        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'
        )
Example #9
0
 def testGetRepositoryRootGood(self):
     root_path = gcl.os.path.join('bleh', 'prout', 'pouet')
     gcl.os.getcwd().AndReturn(root_path)
     gcl.SVN.GetCheckoutRoot(root_path).AndReturn(root_path + '.~')
     self.mox.ReplayAll()
     self.assertEquals(gcl.GetRepositoryRoot(), root_path + '.~')
Example #10
0
def GetSourceRoot():
    """Returns the absolute directory one level up from the repository root."""
    # TODO(maruel): This is odd to assume that '..' is the source root.
    return os.path.abspath(os.path.join(gcl.GetRepositoryRoot(), '..'))
Example #11
0
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