def main(argv):
  assert len(argv) == 1, "No arguments expected"
  upfn = upstream
  cur = current_branch()
  if cur == 'HEAD':
    def _upfn(b):
      parent = upstream(b)
      if parent:
        return hash_one(parent)
    upfn = _upfn
    cur = hash_one(cur)
  downstreams = [b for b in branches() if upfn(b) == cur]
  if not downstreams:
    return "No downstream branches"
  elif len(downstreams) == 1:
    run('checkout', downstreams[0])
  else:
    high = len(downstreams) - 1
    print
    while True:
      print "Please select a downstream branch"
      for i, b in enumerate(downstreams):
        print "  %d. %s" % (i, b)
      r = raw_input("Selection (0-%d)[0]: " % high).strip() or '0'
      if not r.isdigit() or (0 > int(r) > high):
        print "Invalid choice."
      else:
        run('checkout', downstreams[int(r)])
        break
def main(argv):
    assert len(argv) == 1, "No arguments expected"
    upfn = upstream
    cur = current_branch()
    if cur == 'HEAD':

        def _upfn(b):
            parent = upstream(b)
            if parent:
                return hash_one(parent)

        upfn = _upfn
        cur = hash_one(cur)
    downstreams = [b for b in branches() if upfn(b) == cur]
    if not downstreams:
        return "No downstream branches"
    elif len(downstreams) == 1:
        run('checkout', downstreams[0])
    else:
        high = len(downstreams) - 1
        print
        while True:
            print "Please select a downstream branch"
            for i, b in enumerate(downstreams):
                print "  %d. %s" % (i, b)
            r = raw_input("Selection (0-%d)[0]: " % high).strip() or '0'
            if not r.isdigit() or (0 > int(r) > high):
                print "Invalid choice."
            else:
                run('checkout', downstreams[int(r)])
                break
def main(argv):
    colorama.init()
    assert len(argv) == 1, "No arguments expected"
    branch_map = {}
    par_map = collections.defaultdict(list)
    for branch in branches():
        par = upstream(branch) or NO_UPSTREAM
        branch_map[branch] = par
        par_map[par].append(branch)

    current = current_branch()
    hashes = hash_multi(current, *branch_map.keys())
    current_hash = hashes[0]
    par_hashes = {
        k: hashes[i + 1]
        for i, k in enumerate(branch_map.iterkeys())
    }
    par_hashes[NO_UPSTREAM] = 0
    tag_set = tags()
    while par_map:
        for parent in par_map:
            if parent not in branch_map:
                if parent not in par_hashes:
                    par_hashes[parent] = hash_one(parent)
                print_branch(current, current_hash, parent, par_hashes,
                             par_map, branch_map, tag_set)
                break
Exemple #4
0
def main(argv, outbuf):
    if '-h' in argv or '--help' in argv:
        _print_help(outbuf)
        return 0

    map_extra = git_common.get_config_list('depot_tools.map_extra')
    cmd = [
        git_common.GIT_EXE, 'log',
        git_common.root(), '--graph', '--branches', '--tags', '--color=always',
        '--date=short', '--pretty=format:%H%x00%D%x00%cd%x00%s'
    ] + map_extra + argv

    log_proc = subprocess2.Popen(cmd, stdout=subprocess2.PIPE, shell=False)

    current = git_common.current_branch()
    all_tags = set(git_common.tags())
    all_branches = set(git_common.branches())
    if current in all_branches:
        all_branches.remove(current)

    merge_base_map = {}
    for branch in all_branches:
        merge_base = git_common.get_or_create_merge_base(branch)
        if merge_base:
            merge_base_map.setdefault(merge_base, set()).add(branch)

    for merge_base, branches in merge_base_map.items():
        merge_base_map[merge_base] = ', '.join(branches)

    try:
        for line in log_proc.stdout:
            if b'\x00' not in line:
                outbuf.write(line)
                continue

            graph, commit, branch_list, commit_date, subject = _parse_log_line(
                line)

            if 'HEAD' in branch_list:
                graph = graph.replace('*', BLUE_BACK + '*')

            line = '{graph}{commit}\t{branches}{date} ~ {subject}'.format(
                graph=graph,
                commit=BRIGHT_RED + commit[:10] + RESET,
                branches=_color_branch_list(branch_list, all_branches,
                                            all_tags, current),
                date=YELLOW + commit_date + RESET,
                subject=subject)

            if commit in merge_base_map:
                line += '    <({})'.format(WHITE + merge_base_map[commit] +
                                           RESET)

            line += os.linesep
            outbuf.write(line.encode('utf-8', 'replace'))
    except (BrokenPipeError, KeyboardInterrupt):
        pass
    return 0
Exemple #5
0
def CreateBranchForDirectory(prefix, directory, upstream):
    """Creates a branch named |prefix| + "_" + |directory| + "_split".

  Return false if the branch already exists. |upstream| is used as upstream for
  the created branch.
  """
    existing_branches = set(git.branches(use_limit=False))
    branch_name = prefix + '_' + directory + '_split'
    if branch_name in existing_branches:
        return False
    git.run('checkout', '-t', upstream, '-b', branch_name)
    return True
Exemple #6
0
def CreateBranchForDirectory(prefix, directory, upstream):
  """Creates a branch named |prefix| + "_" + |directory| + "_split".

  Return false if the branch already exists. |upstream| is used as upstream for
  the created branch.
  """
  existing_branches = set(git.branches(use_limit = False))
  branch_name = prefix + '_' + directory + '_split'
  if branch_name in existing_branches:
    return False
  git.run('checkout', '-t', upstream, '-b', branch_name)
  return True
Exemple #7
0
def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('--pick',
                        help=('The number to pick if this command would '
                              'prompt'))
    opts = parser.parse_args(args)

    upfn = upstream
    cur = current_branch()
    if cur == 'HEAD':

        def _upfn(b):
            parent = upstream(b)
            if parent:
                return hash_one(parent)

        upfn = _upfn
        cur = hash_one(cur)
    downstreams = [b for b in branches() if upfn(b) == cur]
    if not downstreams:
        return "No downstream branches"
    elif len(downstreams) == 1:
        run_stream('checkout',
                   downstreams[0],
                   stdout=sys.stdout,
                   stderr=sys.stderr)
    else:
        high = len(downstreams) - 1
        while True:
            print "Please select a downstream branch"
            for i, b in enumerate(downstreams):
                print "  %d. %s" % (i, b)
            prompt = "Selection (0-%d)[0]: " % high
            r = opts.pick
            if r:
                print prompt + r
            else:
                r = raw_input(prompt).strip() or '0'
            if not r.isdigit() or (0 > int(r) > high):
                print "Invalid choice."
            else:
                run_stream('checkout',
                           downstreams[int(r)],
                           stdout=sys.stdout,
                           stderr=sys.stderr)
                break
def main(args):
  parser = argparse.ArgumentParser()
  parser.add_argument('--pick',
                      help=(
                          'The number to pick if this command would '
                          'prompt'))
  opts = parser.parse_args(args)

  upfn = upstream
  cur = current_branch()
  if cur == 'HEAD':
    def _upfn(b):
      parent = upstream(b)
      if parent:
        return hash_one(parent)
    upfn = _upfn
    cur = hash_one(cur)
  downstreams = [b for b in branches() if upfn(b) == cur]
  if not downstreams:
    print "No downstream branches"
    return 1
  elif len(downstreams) == 1:
    run('checkout', downstreams[0], stdout=sys.stdout, stderr=sys.stderr)
  else:
    high = len(downstreams) - 1
    while True:
      print "Please select a downstream branch"
      for i, b in enumerate(downstreams):
        print "  %d. %s" % (i, b)
      prompt = "Selection (0-%d)[0]: " % high
      r = opts.pick
      if r:
        print prompt + r
      else:
        r = raw_input(prompt).strip() or '0'
      if not r.isdigit() or (0 > int(r) > high):
        print "Invalid choice."
      else:
        run('checkout', downstreams[int(r)], stdout=sys.stdout,
            stderr=sys.stderr)
        break
  return 0
def main(argv):
  colorama.init()
  assert len(argv) == 1, "No arguments expected"
  branch_map = {}
  par_map = collections.defaultdict(list)
  for branch in branches():
    par = upstream(branch) or NO_UPSTREAM
    branch_map[branch] = par
    par_map[par].append(branch)

  current = current_branch()
  hashes = hash_multi(current, *branch_map.keys())
  current_hash = hashes[0]
  par_hashes = {k: hashes[i+1] for i, k in enumerate(branch_map.iterkeys())}
  par_hashes[NO_UPSTREAM] = 0
  tag_set = tags()
  while par_map:
    for parent in par_map:
      if parent not in branch_map:
        if parent not in par_hashes:
          par_hashes[parent] = hash_one(parent)
        print_branch(current, current_hash, parent, par_hashes, par_map,
                     branch_map, tag_set)
        break
def main(args=None):
  parser = argparse.ArgumentParser()
  parser.add_argument('--verbose', '-v', action='store_true')
  parser.add_argument('--keep-going', '-k', action='store_true',
                      help='Keep processing past failed rebases.')
  parser.add_argument('--no_fetch', '--no-fetch', '-n',
                      action='store_true',
                      help='Skip fetching remotes.')
  opts = parser.parse_args(args)

  if opts.verbose:  # pragma: no cover
    logging.getLogger().setLevel(logging.DEBUG)

  # TODO(iannucci): snapshot all branches somehow, so we can implement
  #                 `git rebase-update --undo`.
  #   * Perhaps just copy packed-refs + refs/ + logs/ to the side?
  #     * commit them to a secret ref?
  #       * Then we could view a summary of each run as a
  #         `diff --stat` on that secret ref.

  if git.in_rebase():
    # TODO(iannucci): Be able to resume rebase with flags like --continue,
    # etc.
    print (
      'Rebase in progress. Please complete the rebase before running '
      '`git rebase-update`.'
    )
    return 1

  return_branch, return_workdir = find_return_branch_workdir()
  os.chdir(git.run('rev-parse', '--show-toplevel'))

  if git.current_branch() == 'HEAD':
    if git.run('status', '--porcelain'):
      print 'Cannot rebase-update with detached head + uncommitted changes.'
      return 1
  else:
    git.freeze()  # just in case there are any local changes.

  skipped, branch_tree = git.get_branch_tree()
  for branch in skipped:
    print 'Skipping %s: No upstream specified' % branch

  if not opts.no_fetch:
    fetch_remotes(branch_tree)

  merge_base = {}
  for branch, parent in branch_tree.iteritems():
    merge_base[branch] = git.get_or_create_merge_base(branch, parent)

  logging.debug('branch_tree: %s' % pformat(branch_tree))
  logging.debug('merge_base: %s' % pformat(merge_base))

  retcode = 0
  unrebased_branches = []
  # Rebase each branch starting with the root-most branches and working
  # towards the leaves.
  for branch, parent in git.topo_iter(branch_tree):
    if git.is_dormant(branch):
      print 'Skipping dormant branch', branch
    else:
      ret = rebase_branch(branch, parent, merge_base[branch])
      if not ret:
        retcode = 1

        if opts.keep_going:
          print '--keep-going set, continuing with next branch.'
          unrebased_branches.append(branch)
          if git.in_rebase():
            git.run_with_retcode('rebase', '--abort')
          if git.in_rebase():  # pragma: no cover
            print 'Failed to abort rebase. Something is really wrong.'
            break
        else:
          break

  if unrebased_branches:
    print
    print 'The following branches could not be cleanly rebased:'
    for branch in unrebased_branches:
      print '  %s' % branch

  if not retcode:
    remove_empty_branches(branch_tree)

    # return_branch may not be there any more.
    if return_branch in git.branches():
      git.run('checkout', return_branch)
      git.thaw()
    else:
      root_branch = git.root()
      if return_branch != 'HEAD':
        print (
          "%r was merged with its parent, checking out %r instead."
          % (return_branch, root_branch)
        )
      git.run('checkout', root_branch)
    if return_workdir:
      os.chdir(return_workdir)
    git.set_config(STARTING_BRANCH_KEY, '')
    git.set_config(STARTING_WORKDIR_KEY, '')

  return retcode
def main(args=None):
    parser = argparse.ArgumentParser()
    parser.add_argument('--verbose', '-v', action='store_true')
    parser.add_argument('--no_fetch',
                        '--no-fetch',
                        '-n',
                        action='store_true',
                        help='Skip fetching remotes.')
    opts = parser.parse_args(args)

    if opts.verbose:  # pragma: no cover
        logging.getLogger().setLevel(logging.DEBUG)

    # TODO(iannucci): snapshot all branches somehow, so we can implement
    #                 `git rebase-update --undo`.
    #   * Perhaps just copy packed-refs + refs/ + logs/ to the side?
    #     * commit them to a secret ref?
    #       * Then we could view a summary of each run as a
    #         `diff --stat` on that secret ref.

    if git.in_rebase():
        # TODO(iannucci): Be able to resume rebase with flags like --continue,
        # etc.
        print(
            'Rebase in progress. Please complete the rebase before running '
            '`git rebase-update`.')
        return 1

    return_branch, return_workdir = find_return_branch_workdir()
    os.chdir(git.run('rev-parse', '--show-toplevel'))

    if git.current_branch() == 'HEAD':
        if git.run('status', '--porcelain'):
            print 'Cannot rebase-update with detached head + uncommitted changes.'
            return 1
    else:
        git.freeze()  # just in case there are any local changes.

    skipped, branch_tree = git.get_branch_tree()
    for branch in skipped:
        print 'Skipping %s: No upstream specified' % branch

    if not opts.no_fetch:
        fetch_remotes(branch_tree)

    merge_base = {}
    for branch, parent in branch_tree.iteritems():
        merge_base[branch] = git.get_or_create_merge_base(branch, parent)

    logging.debug('branch_tree: %s' % pformat(branch_tree))
    logging.debug('merge_base: %s' % pformat(merge_base))

    retcode = 0
    # Rebase each branch starting with the root-most branches and working
    # towards the leaves.
    for branch, parent in git.topo_iter(branch_tree):
        if git.is_dormant(branch):
            print 'Skipping dormant branch', branch
        else:
            ret = rebase_branch(branch, parent, merge_base[branch])
            if not ret:
                retcode = 1
                break

    if not retcode:
        remove_empty_branches(branch_tree)

        # return_branch may not be there any more.
        if return_branch in git.branches():
            git.run('checkout', return_branch)
            git.thaw()
        else:
            root_branch = git.root()
            if return_branch != 'HEAD':
                print(
                    "%r was merged with its parent, checking out %r instead." %
                    (return_branch, root_branch))
            git.run('checkout', root_branch)
        if return_workdir:
            os.chdir(return_workdir)
        git.set_config(STARTING_BRANCH_KEY, '')
        git.set_config(STARTING_WORKDIR_KEY, '')

    return retcode
Exemple #12
0
def main(args=None):
  parser = argparse.ArgumentParser()
  parser.add_argument('--verbose', '-v', action='store_true')
  parser.add_argument('--keep-going', '-k', action='store_true',
                      help='Keep processing past failed rebases.')
  parser.add_argument('--no_fetch', '--no-fetch', '-n',
                      action='store_true',
                      help='Skip fetching remotes.')
  parser.add_argument(
      '--current', action='store_true', help='Only rebase the current branch.')
  parser.add_argument('branches', nargs='*',
                      help='Branches to be rebased. All branches are assumed '
                           'if none specified.')
  opts = parser.parse_args(args)

  if opts.verbose:  # pragma: no cover
    logging.getLogger().setLevel(logging.DEBUG)

  # TODO(iannucci): snapshot all branches somehow, so we can implement
  #                 `git rebase-update --undo`.
  #   * Perhaps just copy packed-refs + refs/ + logs/ to the side?
  #     * commit them to a secret ref?
  #       * Then we could view a summary of each run as a
  #         `diff --stat` on that secret ref.

  if git.in_rebase():
    # TODO(iannucci): Be able to resume rebase with flags like --continue,
    # etc.
    print('Rebase in progress. Please complete the rebase before running '
          '`git rebase-update`.')
    return 1

  return_branch, return_workdir = find_return_branch_workdir()
  os.chdir(git.run('rev-parse', '--show-toplevel'))

  if git.current_branch() == 'HEAD':
    if git.run('status', '--porcelain'):
      print('Cannot rebase-update with detached head + uncommitted changes.')
      return 1
  else:
    git.freeze()  # just in case there are any local changes.

  branches_to_rebase = set(opts.branches)
  if opts.current:
    branches_to_rebase.add(git.current_branch())

  skipped, branch_tree = git.get_branch_tree()
  if branches_to_rebase:
    skipped = set(skipped).intersection(branches_to_rebase)
  for branch in skipped:
    print('Skipping %s: No upstream specified' % branch)

  if not opts.no_fetch:
    fetch_remotes(branch_tree)

  merge_base = {}
  for branch, parent in branch_tree.items():
    merge_base[branch] = git.get_or_create_merge_base(branch, parent)

  logging.debug('branch_tree: %s' % pformat(branch_tree))
  logging.debug('merge_base: %s' % pformat(merge_base))

  retcode = 0
  unrebased_branches = []
  # Rebase each branch starting with the root-most branches and working
  # towards the leaves.
  for branch, parent in git.topo_iter(branch_tree):
    # Only rebase specified branches, unless none specified.
    if branches_to_rebase and branch not in branches_to_rebase:
      continue
    if git.is_dormant(branch):
      print('Skipping dormant branch', branch)
    else:
      ret = rebase_branch(branch, parent, merge_base[branch])
      if not ret:
        retcode = 1

        if opts.keep_going:
          print('--keep-going set, continuing with next branch.')
          unrebased_branches.append(branch)
          if git.in_rebase():
            git.run_with_retcode('rebase', '--abort')
          if git.in_rebase():  # pragma: no cover
            print('Failed to abort rebase. Something is really wrong.')
            break
        else:
          break

  if unrebased_branches:
    print()
    print('The following branches could not be cleanly rebased:')
    for branch in unrebased_branches:
      print('  %s' % branch)

  if not retcode:
    remove_empty_branches(branch_tree)

    # return_branch may not be there any more.
    if return_branch in git.branches():
      git.run('checkout', return_branch)
      git.thaw()
    else:
      root_branch = git.root()
      if return_branch != 'HEAD':
        print("%s was merged with its parent, checking out %s instead." %
              (git.unicode_repr(return_branch), git.unicode_repr(root_branch)))
      git.run('checkout', root_branch)

    # return_workdir may also not be there any more.
    if return_workdir:
      try:
        os.chdir(return_workdir)
      except OSError as e:
        print(
            "Unable to return to original workdir %r: %s" % (return_workdir, e))
    git.set_config(STARTING_BRANCH_KEY, '')
    git.set_config(STARTING_WORKDIR_KEY, '')

  return retcode
Exemple #13
0
def main(argv):
  if '-h' in argv:
    print_help()
    return 0

  map_extra = get_config_list('depot_tools.map_extra')
  fmt = '%C(red bold)%h%x09%Creset%C(green)%d%Creset %C(yellow)%cd%Creset ~ %s'
  log_proc = subprocess2.Popen(
    [GIT_EXE, 'log', '--graph', '--branches', '--tags', root(),
     '--color=always', '--date=short', ('--pretty=format:' + fmt)
    ] + map_extra + argv,
    stdout=subprocess2.PIPE,
    shell=False)

  current = current_branch()
  all_branches = set(branches())
  merge_base_map = {b: get_or_create_merge_base(b) for b in all_branches}
  merge_base_map = {b: v for b, v in merge_base_map.iteritems() if v}
  if current in all_branches:
    all_branches.remove(current)
  all_tags = set(tags())
  try:
    for line in log_proc.stdout.xreadlines():
      if merge_base_map:
        commit = line[line.find(BRIGHT_RED)+len(BRIGHT_RED):line.find('\t')]
        base_for_branches = set()
        for branch, sha in merge_base_map.iteritems():
          if sha.startswith(commit):
            base_for_branches.add(branch)
        if base_for_branches:
          newline = '\r\n' if line.endswith('\r\n') else '\n'
          line = line.rstrip(newline)
          line += ''.join(
              (BRIGHT, WHITE, '    <(%s)' % (', '.join(base_for_branches)),
               RESET, newline))
          for b in base_for_branches:
            del merge_base_map[b]

      start = line.find(GREEN+' (')
      end   = line.find(')', start)
      if start != -1 and end != -1:
        start += len(GREEN) + 2
        branch_list = line[start:end].split(', ')
        branches_str = ''
        if branch_list:
          colored_branches = []
          head_marker = ''
          for b in branch_list:
            if b == "HEAD":
              head_marker = BLUEBAK+BRIGHT+'*'
              continue
            if b == current:
              colored_branches.append(CYAN+BRIGHT+b+RESET)
              current = None
            elif b in all_branches:
              colored_branches.append(GREEN+BRIGHT+b+RESET)
              all_branches.remove(b)
            elif b in all_tags:
              colored_branches.append(MAGENTA+BRIGHT+b+RESET)
            elif b.startswith('tag: '):
              colored_branches.append(MAGENTA+BRIGHT+b[5:]+RESET)
            else:
              colored_branches.append(RED+b)
            branches_str = '(%s) ' % ((GREEN+", ").join(colored_branches)+GREEN)
          line = "%s%s%s" % (line[:start-1], branches_str, line[end+5:])
          if head_marker:
            line = line.replace('*', head_marker, 1)
      sys.stdout.write(line)
  except (IOError, KeyboardInterrupt):
    pass
  finally:
    sys.stderr.close()
    sys.stdout.close()
  return 0
Exemple #14
0
def main(argv):
    if '-h' in argv:
        print_help()
        return 0

    map_extra = get_config_list('depot_tools.map_extra')
    fmt = '%C(red bold)%h%x09%Creset%C(green)%d%Creset %C(yellow)%cd%Creset ~ %s'
    log_proc = subprocess2.Popen([
        GIT_EXE, 'log', '--graph', '--branches', '--tags',
        root(), '--color=always', '--date=short', ('--pretty=format:' + fmt)
    ] + map_extra + argv,
                                 stdout=subprocess2.PIPE,
                                 shell=False)

    current = current_branch()
    all_branches = set(branches())
    merge_base_map = {b: get_or_create_merge_base(b) for b in all_branches}
    merge_base_map = {b: v for b, v in merge_base_map.items() if v}
    if current in all_branches:
        all_branches.remove(current)
    all_tags = set(tags())
    try:
        for line in log_proc.stdout.xreadlines():
            if merge_base_map:
                commit = line[line.find(BRIGHT_RED) +
                              len(BRIGHT_RED):line.find('\t')]
                base_for_branches = set()
                for branch, sha in merge_base_map.items():
                    if sha.startswith(commit):
                        base_for_branches.add(branch)
                if base_for_branches:
                    newline = '\r\n' if line.endswith('\r\n') else '\n'
                    line = line.rstrip(newline)
                    line += ''.join(
                        (BRIGHT, WHITE,
                         '    <(%s)' % (', '.join(base_for_branches)), RESET,
                         newline))
                    for b in base_for_branches:
                        del merge_base_map[b]

            start = line.find(GREEN + ' (')
            end = line.find(')', start)
            if start != -1 and end != -1:
                start += len(GREEN) + 2
                branch_list = line[start:end].split(', ')
                branches_str = ''
                if branch_list:
                    colored_branches = []
                    head_marker = ''
                    for b in branch_list:
                        if b == "HEAD":
                            head_marker = BLUEBAK + BRIGHT + '*'
                            continue
                        if b == current:
                            colored_branches.append(CYAN + BRIGHT + b + RESET)
                            current = None
                        elif b in all_branches:
                            colored_branches.append(GREEN + BRIGHT + b + RESET)
                            all_branches.remove(b)
                        elif b in all_tags:
                            colored_branches.append(MAGENTA + BRIGHT + b +
                                                    RESET)
                        elif b.startswith('tag: '):
                            colored_branches.append(MAGENTA + BRIGHT + b[5:] +
                                                    RESET)
                        else:
                            colored_branches.append(RED + b)
                        branches_str = '(%s) ' % (
                            (GREEN + ", ").join(colored_branches) + GREEN)
                    line = "%s%s%s" % (line[:start - 1], branches_str,
                                       line[end + 5:])
                    if head_marker:
                        line = line.replace('*', head_marker, 1)
            sys.stdout.write(line)
    except (IOError, KeyboardInterrupt):
        pass
    finally:
        sys.stderr.close()
        sys.stdout.close()
    return 0