コード例 #1
0
  def start(self):
    self.__branches_info = get_branches_info(
        include_tracking_status=self.verbosity >= 1)
    roots = set()

    # A map of parents to a list of their children.
    for branch, branch_info in self.__branches_info.iteritems():
      if not branch_info:
        continue

      parent = branch_info.upstream
      if parent and not self.__branches_info[parent]:
        branch_upstream = upstream(branch)
        # If git can't find the upstream, mark the upstream as gone.
        if branch_upstream:
          parent = branch_upstream
        else:
          self.__gone_branches.add(parent)
        # A parent that isn't in the branches info is a root.
        roots.add(parent)

      self.__parent_map[parent].append(branch)

    self.__current_branch = current_branch()
    self.__current_hash = hash_one('HEAD', short=True)
    self.__tag_set = tags()

    if roots:
      for root in sorted(roots):
        self.__append_branch(root)
    else:
      no_branches = OutputLine()
      no_branches.append('No User Branches')
      self.output.append(no_branches)
コード例 #2
0
def fetch_remotes(branch_tree):
  """Fetches all remotes which are needed to update |branch_tree|."""
  fetch_tags = False
  remotes = set()
  tag_set = git.tags()
  for parent in branch_tree.itervalues():
    if parent in tag_set:
      fetch_tags = True
    else:
      full_ref = git.run('rev-parse', '--symbolic-full-name', parent)
      if full_ref.startswith('refs/remotes'):
        parts = full_ref.split('/')
        remote_name = parts[2]
        remotes.add(remote_name)

  fetch_args = []
  if fetch_tags:
    # Need to fetch all because we don't know what remote the tag comes from :(
    # TODO(iannucci): assert that the tags are in the remote fetch refspec
    fetch_args = ['--all']
  else:
    fetch_args.append('--multiple')
    fetch_args.extend(remotes)
  # TODO(iannucci): Should we fetch git-svn?

  if not fetch_args:  # pragma: no cover
    print 'Nothing to fetch.'
  else:
    git.run_with_stderr('fetch', *fetch_args, stdout=sys.stdout,
                        stderr=sys.stderr)
コード例 #3
0
def main(args):
  parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter
  )
  parser.add_argument('branch_name')
  g = parser.add_mutually_exclusive_group()
  g.add_argument('--upstream_current', action='store_true',
                 help='set upstream branch to current branch.')
  g.add_argument('--upstream', metavar='REF', default=root(),
                 help='upstream branch (or tag) to track.')
  g.add_argument('--lkgr', action='store_const', const='lkgr', dest='upstream',
                 help='set basis ref for new branch to lkgr.')

  opts = parser.parse_args(args)

  try:
    if opts.upstream_current:
      run('checkout', '--track', '-b', opts.branch_name)
    else:
      if opts.upstream in tags():
        # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
        run('checkout', '--no-track', '-b', opts.branch_name,
            hash_one(opts.upstream))
        set_config('branch.%s.remote' % opts.branch_name, '.')
        set_config('branch.%s.merge' % opts.branch_name, opts.upstream)
      else:
        # TODO(iannucci): Detect unclean workdir then stash+pop if we need to
        # teleport to a conflicting portion of history?
        run('checkout', '--track', opts.upstream, '-b', opts.branch_name)

    get_or_create_merge_base(opts.branch_name)
  except subprocess2.CalledProcessError as cpe:
    sys.stdout.write(cpe.stdout)
    sys.stderr.write(cpe.stderr)
    return 1
コード例 #4
0
def remove_empty_branches(branch_tree):
    tag_set = git.tags()
    ensure_root_checkout = git.once(lambda: git.run('checkout', git.root()))

    deletions = set()
    downstreams = collections.defaultdict(list)
    for branch, parent in git.topo_iter(branch_tree, top_down=False):
        downstreams[parent].append(branch)

        if git.hash_one(branch) == git.hash_one(parent):
            ensure_root_checkout()

            logging.debug('branch %s merged to %s', branch, parent)

            for down in downstreams[branch]:
                if down in deletions:
                    continue

                if parent in tag_set:
                    git.set_branch_config(down, 'remote', '.')
                    git.set_branch_config(down, 'merge',
                                          'refs/tags/%s' % parent)
                    print('Reparented %s to track %s [tag] (was tracking %s)' %
                          (down, parent, branch))
                else:
                    git.run('branch', '--set-upstream-to', parent, down)
                    print('Reparented %s to track %s (was tracking %s)' %
                          (down, parent, branch))

            deletions.add(branch)
            print git.run('branch', '-d', branch)
コード例 #5
0
    def start(self):
        self.__branches_info = get_branches_info(
            include_tracking_status=self.verbosity >= 1)
        roots = set()

        # A map of parents to a list of their children.
        for branch, branch_info in self.__branches_info.iteritems():
            if not branch_info:
                continue

            parent = branch_info.upstream
            if not self.__branches_info[parent]:
                branch_upstream = upstream(branch)
                # If git can't find the upstream, mark the upstream as gone.
                if branch_upstream:
                    parent = branch_upstream
                else:
                    self.__gone_branches.add(parent)
                # A parent that isn't in the branches info is a root.
                roots.add(parent)

            self.__parent_map[parent].append(branch)

        self.__current_branch = current_branch()
        self.__current_hash = hash_one('HEAD', short=True)
        self.__tag_set = tags()

        if roots:
            for root in sorted(roots):
                self.__append_branch(root)
        else:
            no_branches = OutputLine()
            no_branches.append('No User Branches')
            self.output.append(no_branches)
コード例 #6
0
def remove_empty_branches(branch_tree):
    tag_set = git.tags()
    ensure_root_checkout = git.once(lambda: git.run("checkout", git.root()))

    deletions = set()
    downstreams = collections.defaultdict(list)
    for branch, parent in git.topo_iter(branch_tree, top_down=False):
        downstreams[parent].append(branch)

        if git.hash_one(branch) == git.hash_one(parent):
            ensure_root_checkout()

            logging.debug("branch %s merged to %s", branch, parent)

            for down in downstreams[branch]:
                if down in deletions:
                    continue

                if parent in tag_set:
                    git.set_branch_config(down, "remote", ".")
                    git.set_branch_config(down, "merge", "refs/tags/%s" % parent)
                    print ("Reparented %s to track %s [tag] (was tracking %s)" % (down, parent, branch))
                else:
                    git.run("branch", "--set-upstream-to", parent, down)
                    print ("Reparented %s to track %s (was tracking %s)" % (down, parent, branch))

            deletions.add(branch)
            print git.run("branch", "-d", branch)
コード例 #7
0
def fetch_remotes(branch_tree):
    """Fetches all remotes which are needed to update |branch_tree|."""
    fetch_tags = False
    remotes = set()
    tag_set = git.tags()
    for parent in branch_tree.itervalues():
        if parent in tag_set:
            fetch_tags = True
        else:
            full_ref = git.run('rev-parse', '--symbolic-full-name', parent)
            if full_ref.startswith('refs/remotes'):
                parts = full_ref.split('/')
                remote_name = parts[2]
                remotes.add(remote_name)

    fetch_args = []
    if fetch_tags:
        # Need to fetch all because we don't know what remote the tag comes from :(
        # TODO(iannucci): assert that the tags are in the remote fetch refspec
        fetch_args = ['--all']
    else:
        fetch_args.append('--multiple')
        fetch_args.extend(remotes)
    # TODO(iannucci): Should we fetch git-svn?

    if not fetch_args:  # pragma: no cover
        print 'Nothing to fetch.'
    else:
        git.run_with_stderr('fetch',
                            *fetch_args,
                            stdout=sys.stdout,
                            stderr=sys.stderr)
コード例 #8
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
コード例 #9
0
def main(args):
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description=__doc__,
    )
    parser.add_argument('branch_name')
    g = parser.add_mutually_exclusive_group()
    g.add_argument('--upstream-current',
                   '--upstream_current',
                   action='store_true',
                   help='set upstream branch to current branch.')
    g.add_argument('--upstream',
                   metavar='REF',
                   default=root(),
                   help='upstream branch (or tag) to track.')
    g.add_argument('--inject-current',
                   '--inject_current',
                   action='store_true',
                   help='new branch adopts current branch\'s upstream,' +
                   ' and new branch becomes current branch\'s upstream.')
    g.add_argument('--lkgr',
                   action='store_const',
                   const='lkgr',
                   dest='upstream',
                   help='set basis ref for new branch to lkgr.')

    opts = parser.parse_args(args)

    try:
        if opts.inject_current:
            below = current_branch()
            if below is None:
                raise Exception('no current branch')
            above = upstream(below)
            if above is None:
                raise Exception('branch %s has no upstream' % (below))
            run('checkout', '--track', above, '-b', opts.branch_name)
            run('branch', '--set-upstream-to', opts.branch_name, below)
        elif opts.upstream_current:
            run('checkout', '--track', '-b', opts.branch_name)
        else:
            if opts.upstream in tags():
                # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
                run('checkout', '--no-track', '-b', opts.branch_name,
                    hash_one(opts.upstream))
                set_config('branch.%s.remote' % opts.branch_name, '.')
                set_config('branch.%s.merge' % opts.branch_name, opts.upstream)
            else:
                # TODO(iannucci): Detect unclean workdir then stash+pop if we need to
                # teleport to a conflicting portion of history?
                run('checkout', '--track', opts.upstream, '-b',
                    opts.branch_name)
        get_or_create_merge_base(opts.branch_name)
    except subprocess2.CalledProcessError as cpe:
        sys.stdout.write(cpe.stdout)
        sys.stderr.write(cpe.stderr)
        return 1
    sys.stderr.write('Switched to branch %s.\n' % opts.branch_name)
    return 0
コード例 #10
0
def main(args):
    root_ref = root()

    parser = argparse.ArgumentParser()
    g = parser.add_mutually_exclusive_group()
    g.add_argument('new_parent',
                   nargs='?',
                   help='New parent branch (or tag) to reparent to.')
    g.add_argument('--root',
                   action='store_true',
                   help='Reparent to the configured root branch (%s).' %
                   root_ref)
    g.add_argument('--lkgr',
                   action='store_true',
                   help='Reparent to the lkgr tag.')
    opts = parser.parse_args(args)

    # TODO(iannucci): Allow specification of the branch-to-reparent

    branch = current_branch()
    if opts.root:
        new_parent = root_ref
    elif opts.lkgr:
        new_parent = 'lkgr'
    else:
        new_parent = opts.new_parent
    cur_parent = upstream(branch)

    if branch == 'HEAD' or not branch:
        parser.error('Must be on the branch you want to reparent')
    if new_parent == cur_parent:
        parser.error('Cannot reparent a branch to its existing parent')

    mbase = get_or_create_merge_base(branch, cur_parent)

    all_tags = tags()
    if cur_parent in all_tags:
        cur_parent += ' [tag]'

    try:
        run('show-ref', new_parent)
    except subprocess2.CalledProcessError:
        print >> sys.stderr, 'fatal: invalid reference: %s' % new_parent
        return 1

    if new_parent in all_tags:
        print("Reparenting %s to track %s [tag] (was %s)" %
              (branch, new_parent, cur_parent))
        set_branch_config(branch, 'remote', '.')
        set_branch_config(branch, 'merge', new_parent)
    else:
        print("Reparenting %s to track %s (was %s)" %
              (branch, new_parent, cur_parent))
        run('branch', '--set-upstream-to', new_parent, branch)

    manual_merge_base(branch, mbase, new_parent)

    # TODO(iannucci): ONLY rebase-update the branch which moved (and dependants)
    return git_rebase_update.main(['--no-fetch'])
コード例 #11
0
ファイル: git_map.py プロジェクト: lakshmipriyap/cobalt
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
コード例 #12
0
def main(args):
  root_ref = root()

  parser = argparse.ArgumentParser()
  g = parser.add_mutually_exclusive_group()
  g.add_argument('new_parent', nargs='?',
                 help='New parent branch (or tag) to reparent to.')
  g.add_argument('--root', action='store_true',
                 help='Reparent to the configured root branch (%s).' % root_ref)
  g.add_argument('--lkgr', action='store_true',
                 help='Reparent to the lkgr tag.')
  opts = parser.parse_args(args)

  # TODO(iannucci): Allow specification of the branch-to-reparent

  branch = current_branch()
  if opts.root:
    new_parent = root_ref
  elif opts.lkgr:
    new_parent = 'lkgr'
  else:
    if not opts.new_parent:
      parser.error('Must specify new parent somehow')
    new_parent = opts.new_parent
  cur_parent = upstream(branch)

  if branch == 'HEAD' or not branch:
    parser.error('Must be on the branch you want to reparent')
  if new_parent == cur_parent:
    parser.error('Cannot reparent a branch to its existing parent')

  mbase = get_or_create_merge_base(branch, cur_parent)

  all_tags = tags()
  if cur_parent in all_tags:
    cur_parent += ' [tag]'

  try:
    run('show-ref', new_parent)
  except subprocess2.CalledProcessError:
    print >> sys.stderr, 'fatal: invalid reference: %s' % new_parent
    return 1

  if new_parent in all_tags:
    print ("Reparenting %s to track %s [tag] (was %s)"
           % (branch, new_parent, cur_parent))
    set_branch_config(branch, 'remote', '.')
    set_branch_config(branch, 'merge', new_parent)
  else:
    print ("Reparenting %s to track %s (was %s)"
           % (branch, new_parent, cur_parent))
    run('branch', '--set-upstream-to', new_parent, branch)

  manual_merge_base(branch, mbase, new_parent)

  # TODO(iannucci): ONLY rebase-update the branch which moved (and dependants)
  return git_rebase_update.main(['--no-fetch'])
コード例 #13
0
    def start(self):
        self.__branches_info = get_branches_info(
            include_tracking_status=self.verbosity >= 1)
        if (self.verbosity >= 2):
            # Avoid heavy import unless necessary.
            from git_cl import get_cl_statuses, color_for_status, Changelist

            change_cls = [
                Changelist(branchref='refs/heads/' + b)
                for b in self.__branches_info.keys() if b
            ]
            status_info = get_cl_statuses(change_cls,
                                          fine_grained=self.verbosity > 2,
                                          max_processes=self.maxjobs)

            # This is a blocking get which waits for the remote CL status to be
            # retrieved.
            for cl, status in status_info:
                self.__status_info[cl.GetBranch()] = (cl.GetIssueURL(),
                                                      color_for_status(status),
                                                      status)

        roots = set()

        # A map of parents to a list of their children.
        for branch, branch_info in self.__branches_info.items():
            if not branch_info:
                continue

            parent = branch_info.upstream
            if self.__check_cycle(branch):
                continue
            if not self.__branches_info[parent]:
                branch_upstream = upstream(branch)
                # If git can't find the upstream, mark the upstream as gone.
                if branch_upstream:
                    parent = branch_upstream
                else:
                    self.__gone_branches.add(parent)
                # A parent that isn't in the branches info is a root.
                roots.add(parent)

            self.__parent_map[parent].append(branch)

        self.__current_branch = current_branch()
        self.__current_hash = hash_one('HEAD', short=True)
        self.__tag_set = tags()

        if roots:
            for root in sorted(roots):
                self.__append_branch(root)
        else:
            no_branches = OutputLine()
            no_branches.append('No User Branches')
            self.output.append(no_branches)
コード例 #14
0
def remove_empty_branches(branch_tree):
    tag_set = git.tags()
    ensure_root_checkout = git.once(lambda: git.run('checkout', git.root()))

    deletions = {}
    reparents = {}
    downstreams = collections.defaultdict(list)
    for branch, parent in git.topo_iter(branch_tree, top_down=False):
        if git.is_dormant(branch):
            continue

        downstreams[parent].append(branch)

        # If branch and parent have the same tree, then branch has to be marked
        # for deletion and its children and grand-children reparented to parent.
        if git.hash_one(branch + ":") == git.hash_one(parent + ":"):
            ensure_root_checkout()

            logging.debug('branch %s merged to %s', branch, parent)

            # Mark branch for deletion while remembering the ordering, then add all
            # its children as grand-children of its parent and record reparenting
            # information if necessary.
            deletions[branch] = len(deletions)

            for down in downstreams[branch]:
                if down in deletions:
                    continue

                # Record the new and old parent for down, or update such a record
                # if it already exists. Keep track of the ordering so that reparenting
                # happen in topological order.
                downstreams[parent].append(down)
                if down not in reparents:
                    reparents[down] = (len(reparents), parent, branch)
                else:
                    order, _, old_parent = reparents[down]
                    reparents[down] = (order, parent, old_parent)

    # Apply all reparenting recorded, in order.
    for branch, value in sorted(reparents.items(), key=lambda x: x[1][0]):
        _, parent, old_parent = value
        if parent in tag_set:
            git.set_branch_config(branch, 'remote', '.')
            git.set_branch_config(branch, 'merge', 'refs/tags/%s' % parent)
            print('Reparented %s to track %s [tag] (was tracking %s)' %
                  (branch, parent, old_parent))
        else:
            git.run('branch', '--set-upstream-to', parent, branch)
            print('Reparented %s to track %s (was tracking %s)' %
                  (branch, parent, old_parent))

    # Apply all deletions recorded, in order.
    for branch, _ in sorted(deletions.items(), key=lambda x: x[1]):
        print(git.run('branch', '-d', branch))
コード例 #15
0
def remove_empty_branches(branch_tree):
  tag_set = git.tags()
  ensure_root_checkout = git.once(lambda: git.run('checkout', git.root()))

  deletions = {}
  reparents = {}
  downstreams = collections.defaultdict(list)
  for branch, parent in git.topo_iter(branch_tree, top_down=False):
    downstreams[parent].append(branch)

    # If branch and parent have the same tree, then branch has to be marked
    # for deletion and its children and grand-children reparented to parent.
    if git.hash_one(branch+":") == git.hash_one(parent+":"):
      ensure_root_checkout()

      logging.debug('branch %s merged to %s', branch, parent)

      # Mark branch for deletion while remembering the ordering, then add all
      # its children as grand-children of its parent and record reparenting
      # information if necessary.
      deletions[branch] = len(deletions)

      for down in downstreams[branch]:
        if down in deletions:
          continue

        # Record the new and old parent for down, or update such a record
        # if it already exists. Keep track of the ordering so that reparenting
        # happen in topological order.
        downstreams[parent].append(down)
        if down not in reparents:
          reparents[down] = (len(reparents), parent, branch)
        else:
          order, _, old_parent = reparents[down]
          reparents[down] = (order, parent, old_parent)

  # Apply all reparenting recorded, in order.
  for branch, value in sorted(reparents.iteritems(), key=lambda x:x[1][0]):
    _, parent, old_parent = value
    if parent in tag_set:
      git.set_branch_config(branch, 'remote', '.')
      git.set_branch_config(branch, 'merge', 'refs/tags/%s' % parent)
      print ('Reparented %s to track %s [tag] (was tracking %s)'
             % (branch, parent, old_parent))
    else:
      git.run('branch', '--set-upstream-to', parent, branch)
      print ('Reparented %s to track %s (was tracking %s)'
             % (branch, parent, old_parent))

  # Apply all deletions recorded, in order.
  for branch, _ in sorted(deletions.iteritems(), key=lambda x: x[1]):
    print git.run('branch', '-d', branch)
コード例 #16
0
  def start(self):
    self.__branches_info = get_branches_info(
        include_tracking_status=self.verbosity >= 1)
    if (self.verbosity >= 2):
      # Avoid heavy import unless necessary.
      from git_cl import get_cl_statuses, color_for_status, Changelist

      change_cls = [Changelist(branchref='refs/heads/'+b)
                    for b in self.__branches_info.keys() if b]
      status_info = get_cl_statuses(change_cls,
                                    fine_grained=self.verbosity > 2,
                                    max_processes=self.maxjobs)

      # This is a blocking get which waits for the remote CL status to be
      # retrieved.
      for cl, status in status_info:
        self.__status_info[cl.GetBranch()] = (cl.GetIssueURL(),
                                              color_for_status(status),
                                              status)

    roots = set()

    # A map of parents to a list of their children.
    for branch, branch_info in self.__branches_info.iteritems():
      if not branch_info:
        continue

      parent = branch_info.upstream
      if not self.__branches_info[parent]:
        branch_upstream = upstream(branch)
        # If git can't find the upstream, mark the upstream as gone.
        if branch_upstream:
          parent = branch_upstream
        else:
          self.__gone_branches.add(parent)
        # A parent that isn't in the branches info is a root.
        roots.add(parent)

      self.__parent_map[parent].append(branch)

    self.__current_branch = current_branch()
    self.__current_hash = hash_one('HEAD', short=True)
    self.__tag_set = tags()

    if roots:
      for root in sorted(roots):
        self.__append_branch(root)
    else:
      no_branches = OutputLine()
      no_branches.append('No User Branches')
      self.output.append(no_branches)
コード例 #17
0
def main(args):
  parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    description=__doc__,
  )
  parser.add_argument('branch_name')
  g = parser.add_mutually_exclusive_group()
  g.add_argument('--upstream-current', '--upstream_current',
                 action='store_true',
                 help='set upstream branch to current branch.')
  g.add_argument('--upstream', metavar='REF', default=root(),
                 help='upstream branch (or tag) to track.')
  g.add_argument('--inject-current', '--inject_current',
                 action='store_true',
                 help='new branch adopts current branch\'s upstream,' +
                 ' and new branch becomes current branch\'s upstream.')
  g.add_argument('--lkgr', action='store_const', const='lkgr', dest='upstream',
                 help='set basis ref for new branch to lkgr.')

  opts = parser.parse_args(args)

  try:
    if opts.inject_current:
      below = current_branch()
      if below is None:
        raise Exception('no current branch')
      above = upstream(below)
      if above is None:
        raise Exception('branch %s has no upstream' % (below))
      run('checkout', '--track', above, '-b', opts.branch_name)
      run('branch', '--set-upstream-to', opts.branch_name, below)
    elif opts.upstream_current:
      run('checkout', '--track', '-b', opts.branch_name)
    else:
      if opts.upstream in tags():
        # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
        run('checkout', '--no-track', '-b', opts.branch_name,
            hash_one(opts.upstream))
        set_config('branch.%s.remote' % opts.branch_name, '.')
        set_config('branch.%s.merge' % opts.branch_name, opts.upstream)
      else:
        # TODO(iannucci): Detect unclean workdir then stash+pop if we need to
        # teleport to a conflicting portion of history?
        run('checkout', '--track', opts.upstream, '-b', opts.branch_name)
    get_or_create_merge_base(opts.branch_name)
  except subprocess2.CalledProcessError as cpe:
    sys.stdout.write(cpe.stdout)
    sys.stderr.write(cpe.stderr)
    return 1
  sys.stderr.write('Switched to branch %s.\n' % opts.branch_name)
  return 0
コード例 #18
0
    def start(self):
        self.__branches_info = get_branches_info(
            include_tracking_status=self.verbosity >= 1)
        if (self.verbosity >= 2):
            # Avoid heavy import unless necessary.
            from git_cl import get_cl_statuses

            status_info = get_cl_statuses(self.__branches_info.keys(),
                                          fine_grained=self.verbosity > 2,
                                          max_processes=self.maxjobs)

            for _ in xrange(len(self.__branches_info)):
                # This is a blocking get which waits for the remote CL status to be
                # retrieved.
                (branch, url, color) = status_info.next()
                self.__status_info[branch] = (url, color)

        roots = set()

        # A map of parents to a list of their children.
        for branch, branch_info in self.__branches_info.iteritems():
            if not branch_info:
                continue

            parent = branch_info.upstream
            if not self.__branches_info[parent]:
                branch_upstream = upstream(branch)
                # If git can't find the upstream, mark the upstream as gone.
                if branch_upstream:
                    parent = branch_upstream
                else:
                    self.__gone_branches.add(parent)
                # A parent that isn't in the branches info is a root.
                roots.add(parent)

            self.__parent_map[parent].append(branch)

        self.__current_branch = current_branch()
        self.__current_hash = hash_one('HEAD', short=True)
        self.__tag_set = tags()

        if roots:
            for root in sorted(roots):
                self.__append_branch(root)
        else:
            no_branches = OutputLine()
            no_branches.append('No User Branches')
            self.output.append(no_branches)
コード例 #19
0
def main(args):
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('branch_name')
    g = parser.add_mutually_exclusive_group()
    g.add_argument('--upstream_current',
                   action='store_true',
                   help='set upstream branch to current branch.')
    g.add_argument('--upstream',
                   metavar='REF',
                   default=root(),
                   help='upstream branch (or tag) to track.')
    g.add_argument('--lkgr',
                   action='store_const',
                   const='lkgr',
                   dest='upstream',
                   help='set basis ref for new branch to lkgr.')

    opts = parser.parse_args(args)

    try:
        if opts.upstream_current:
            run('checkout', '--track', '-b', opts.branch_name)
        else:
            if opts.upstream in tags():
                # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
                run('checkout', '--no-track', '-b', opts.branch_name,
                    hash_one(opts.upstream))
                set_config('branch.%s.remote' % opts.branch_name, '.')
                set_config('branch.%s.merge' % opts.branch_name, opts.upstream)
            else:
                # TODO(iannucci): Detect unclean workdir then stash+pop if we need to
                # teleport to a conflicting portion of history?
                run('checkout', '--track', opts.upstream, '-b',
                    opts.branch_name)

        get_or_create_merge_base(opts.branch_name)
    except subprocess2.CalledProcessError as cpe:
        sys.stdout.write(cpe.stdout)
        sys.stderr.write(cpe.stderr)
        return 1
コード例 #20
0
def fetch_remotes(branch_tree):
    """Fetches all remotes which are needed to update |branch_tree|."""
    fetch_tags = False
    remotes = set()
    tag_set = git.tags()
    fetchspec_map = {}
    all_fetchspec_configs = git.run('config', '--get-regexp',
                                    r'^remote\..*\.fetch').strip()
    for fetchspec_config in all_fetchspec_configs.splitlines():
        key, _, fetchspec = fetchspec_config.partition(' ')
        dest_spec = fetchspec.partition(':')[2]
        remote_name = key.split('.')[1]
        fetchspec_map[dest_spec] = remote_name
    for parent in branch_tree.itervalues():
        if parent in tag_set:
            fetch_tags = True
        else:
            full_ref = git.run('rev-parse', '--symbolic-full-name', parent)
            for dest_spec, remote_name in fetchspec_map.iteritems():
                if fnmatch(full_ref, dest_spec):
                    remotes.add(remote_name)
                    break

    fetch_args = []
    if fetch_tags:
        # Need to fetch all because we don't know what remote the tag comes from :(
        # TODO(iannucci): assert that the tags are in the remote fetch refspec
        fetch_args = ['--all']
    else:
        fetch_args.append('--multiple')
        fetch_args.extend(remotes)
    # TODO(iannucci): Should we fetch git-svn?

    if not fetch_args:  # pragma: no cover
        print 'Nothing to fetch.'
    else:
        git.run_with_stderr('fetch',
                            *fetch_args,
                            stdout=sys.stdout,
                            stderr=sys.stderr)
コード例 #21
0
def fetch_remotes(branch_tree):
  """Fetches all remotes which are needed to update |branch_tree|."""
  fetch_tags = False
  remotes = set()
  tag_set = git.tags()
  fetchspec_map = {}
  all_fetchspec_configs = git.run(
      'config', '--get-regexp', r'^remote\..*\.fetch').strip()
  for fetchspec_config in all_fetchspec_configs.splitlines():
    key, _, fetchspec = fetchspec_config.partition(' ')
    dest_spec = fetchspec.partition(':')[2]
    remote_name = key.split('.')[1]
    fetchspec_map[dest_spec] = remote_name
  for parent in branch_tree.itervalues():
    if parent in tag_set:
      fetch_tags = True
    else:
      full_ref = git.run('rev-parse', '--symbolic-full-name', parent)
      for dest_spec, remote_name in fetchspec_map.iteritems():
        if fnmatch(full_ref, dest_spec):
          remotes.add(remote_name)
          break

  fetch_args = []
  if fetch_tags:
    # Need to fetch all because we don't know what remote the tag comes from :(
    # TODO(iannucci): assert that the tags are in the remote fetch refspec
    fetch_args = ['--all']
  else:
    fetch_args.append('--multiple')
    fetch_args.extend(remotes)
  # TODO(iannucci): Should we fetch git-svn?

  if not fetch_args:  # pragma: no cover
    print 'Nothing to fetch.'
  else:
    git.run_with_stderr('fetch', *fetch_args, stdout=sys.stdout,
                        stderr=sys.stderr)
コード例 #22
0
def create_new_branch(branch_name,
                      upstream_current=False,
                      upstream=None,
                      inject_current=False):
    upstream = upstream or git_common.root()
    try:
        if inject_current:
            below = git_common.current_branch()
            if below is None:
                raise Exception('no current branch')
            above = git_common.upstream(below)
            if above is None:
                raise Exception('branch %s has no upstream' % (below))
            git_common.run('checkout', '--track', above, '-b', branch_name)
            git_common.run('branch', '--set-upstream-to', branch_name, below)
        elif upstream_current:
            git_common.run('checkout', '--track', '-b', branch_name)
        else:
            if upstream in git_common.tags():
                # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
                git_common.run('checkout', '--no-track', '-b', branch_name,
                               git_common.hash_one(upstream))
                git_common.set_config('branch.%s.remote' % branch_name, '.')
                git_common.set_config('branch.%s.merge' % branch_name,
                                      upstream)
            else:
                # TODO(iannucci): Detect unclean workdir then stash+pop if we need to
                # teleport to a conflicting portion of history?
                git_common.run('checkout', '--track', upstream, '-b',
                               branch_name)
        git_common.get_or_create_merge_base(branch_name)
    except subprocess2.CalledProcessError as cpe:
        sys.stdout.write(cpe.stdout.decode('utf-8', 'replace'))
        sys.stderr.write(cpe.stderr.decode('utf-8', 'replace'))
        return 1
    sys.stderr.write('Switched to branch %s.\n' % branch_name)
    return 0
コード例 #23
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
コード例 #24
0
ファイル: git_map.py プロジェクト: sharpglasses/depot_tools
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
コード例 #25
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
コード例 #26
0
def main(args):
  root_ref = root()

  parser = argparse.ArgumentParser()
  g = parser.add_mutually_exclusive_group()
  g.add_argument('new_parent', nargs='?',
                 help='New parent branch (or tag) to reparent to.')
  g.add_argument('--root', action='store_true',
                 help='Reparent to the configured root branch (%s).' % root_ref)
  g.add_argument('--lkgr', action='store_true',
                 help='Reparent to the lkgr tag.')
  opts = parser.parse_args(args)

  # TODO(iannucci): Allow specification of the branch-to-reparent

  branch = current_branch()

  if opts.root:
    new_parent = root_ref
  elif opts.lkgr:
    new_parent = 'lkgr'
  else:
    if not opts.new_parent:
      parser.error('Must specify new parent somehow')
    new_parent = opts.new_parent
  cur_parent = upstream(branch)

  if branch == 'HEAD' or not branch:
    parser.error('Must be on the branch you want to reparent')
  if new_parent == cur_parent:
    parser.error('Cannot reparent a branch to its existing parent')

  if not cur_parent:
    msg = (
      "Unable to determine %s@{upstream}.\n\nThis can happen if you didn't use "
      "`git new-branch` to create the branch and haven't used "
      "`git branch --set-upstream-to` to assign it one.\n\nPlease assign an "
      "upstream branch and then run this command again."
    )
    print(msg % branch, file=sys.stderr)
    return 1

  mbase = get_or_create_merge_base(branch, cur_parent)

  all_tags = tags()
  if cur_parent in all_tags:
    cur_parent += ' [tag]'

  try:
    run('show-ref', new_parent)
  except subprocess2.CalledProcessError:
    print('fatal: invalid reference: %s' % new_parent, file=sys.stderr)
    return 1

  if new_parent in all_tags:
    print("Reparenting %s to track %s [tag] (was %s)" % (branch, new_parent,
                                                         cur_parent))
    set_branch_config(branch, 'remote', '.')
    set_branch_config(branch, 'merge', new_parent)
  else:
    print("Reparenting %s to track %s (was %s)" % (branch, new_parent,
                                                   cur_parent))
    run('branch', '--set-upstream-to', new_parent, branch)

  manual_merge_base(branch, mbase, new_parent)

  # ONLY rebase-update the branch which moved (and dependants)
  _, branch_tree = get_branch_tree()
  branches = [branch]
  for branch, parent in topo_iter(branch_tree):
    if parent in branches:
      branches.append(branch)
  return git_rebase_update.main(['--no-fetch'] + branches)