Exemple #1
0
def find_tag_rev(url):
    """Return the revision at which a remote tag was created.

  Since tags are immutable by convention, usually the HEAD of a tag
  should be the tag creation revision. However, mistakes can happen,
  so this function will walk the history of the given tag URL,
  stopping on the first revision that was created by copy.

  This detection is not foolproof. For example: it will be fooled by a
  tag that was created, deleted, and recreated by copy at a different
  revision. It is not clear what the desired behavior in these edge
  cases are, and no attempt is made to handle them. You should request
  user confirmation before using the result of this function.

  Args:
    url: The repository URL of the tag to examine.
  """
    try:
        output = util.run(['svn', 'log', '-q', '--stop-on-copy', url],
                          capture=True)
    except util.SubprocessFailed:
        raise error.ExpectationFailed('No tag at URL ' + url)
    first_rev_line = output[-2]
    first_rev = int(first_rev_line.split()[0][1:])
    return first_rev
Exemple #2
0
  def switchToBranch(self):
    """Switch to another Melange release branch"""
    branches = self._listBranches()
    if not branches:
      raise error.ExpectationFailed(
        'No branches available. Please import one.')

    choice = io.getChoice('Available release branches:',
                          'Your choice?',
                          branches,
                          suggest=len(branches)-1)
    self._switchBranch(branches[choice])
Exemple #3
0
def diff(url, revision):
    """Retrieve a revision from a remote repository as a unified diff.

  Args:
    url: The repository URL on which to perform the diff.
    revision: The revision to extract at the given url.

  Returns:
    A string containing the changes extracted from the remote
    repository, in unified diff format suitable for application using
    'patch'.
  """
    try:
        return util.run(
            ['svn', 'diff', '-c', str(revision), url],
            capture=True,
            split_capture=False)
    except util.SubprocessFailed:
        raise error.ExpectationFailed('Could not get diff for r%d '
                                      'from remote repository' % revision)
Exemple #4
0
  def cherryPickChange(self):
    """Cherry-pick a change from the Melange trunk"""
    rev = io.getNumber('Revision number to cherry-pick:')
    bug = io.getNumber('Issue fixed by this change:')

    diff = subversion.diff(self.upstream_repos + '/trunk', rev)
    if not diff.strip():
      raise error.ExpectationFailed(
        'Retrieved diff is empty. '
        'Did you accidentally cherry-pick a branch change?')
    util.run(['patch', '-p0'], cwd=self.wc.path(self.branch_dir), stdin=diff)
    self.wc.addRemove(self.branch_dir)

    yaml_path = self.wc.path(self._branchPath('app/app.yaml'))
    out = []
    updated_patchlevel = False
    for line in io.fileToLines(yaml_path):
      if line.strip().startswith('version: '):
        version = line.strip().split()[-1]
        base, patch = line.rsplit('g', 1)
        new_version = '%sg%d' % (base, int(patch) + 1)
        message = ('Cherry-picked r%d from /p/soc/ to fix issue %d' %
            (rev, bug))
        out.append('version: ' + new_version)
        out.append('# * ' + message)
        updated_patchlevel = True
      else:
        out.append(line)

    if not updated_patchlevel:
      log.error('Failed to update Google patch revision')
      log.error('Cherry-picking failed')

    io.linesToFile(yaml_path, out)

    log.info('Check the diff about to be committed with:')
    log.info('svn diff ' + self.wc.path(self.branch_dir))
    if not io.confirm('Commit this change?'):
      raise error.AbortedByUser('Cherry-pick aborted')
    self.wc.commit(message)
    log.info('Cherry-picked r%d from the Melange trunk.' % rev)
Exemple #5
0
  def _applyGooglePatches(self):
    """Apply Google-specific patches to a vanilla Melange release.

    Each patch is applied and committed in turn.
    """
    # Edit the base template to point users to the Google fork
    # of the Melange codebase instead of the vanilla release.
    tmpl_file = self.wc.path(
      self._branchPath('app/soc/templates/soc/base.html'))
    tmpl = io.fileToLines(tmpl_file)
    for i, line in enumerate(tmpl):
      if 'http://code.google.com/p/soc/source/browse/tags/' in line:
        tmpl[i] = line.replace('/p/soc/', '/p/soc-google/')
        break
    else:
      raise error.ExpectationFailed(
        'No source code link found in base.html')
    io.linesToFile(tmpl_file, tmpl)

    self.wc.commit(
      'Customize the Melange release link in the sidebar menu')
Exemple #6
0
 def check_branch(self, *args, **kwargs):
   if self.branch is None:
     raise error.ExpectationFailed(
       'This operation requires an active release branch')
   return f(self, *args, **kwargs)