Example #1
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)
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)
Example #3
0
def main(args):
  current = current_branch()
  if current == 'HEAD':
    current = None
  old_name_help = 'The old branch to rename.'
  if current:
    old_name_help += ' (default %(default)r)'

  parser = argparse.ArgumentParser()
  parser.add_argument('old_name', nargs=('?' if current else 1),
                      help=old_name_help, default=current)
  parser.add_argument('new_name', help='The new branch name.')

  opts = parser.parse_args(args)

  # when nargs=1, we get a list :(
  if isinstance(opts.old_name, list):
    opts.old_name = opts.old_name[0]

  try:
    run('branch', '-m', opts.old_name, opts.new_name)

    # update the downstreams
    for branch, merge in branch_config_map('merge').items():
      if merge == 'refs/heads/' + opts.old_name:
        # Only care about local branches
        if branch_config(branch, 'remote') == '.':
          set_branch_config(branch, 'merge', 'refs/heads/' + opts.new_name)
  except subprocess2.CalledProcessError as cpe:
    sys.stderr.write(cpe.stderr)
    return 1
  return 0
def main(args):
  current = current_branch()
  if current == 'HEAD':
    current = None
  old_name_help = 'The old branch to rename.'
  if current:
    old_name_help += ' (default %(default)r)'

  parser = argparse.ArgumentParser()
  parser.add_argument('old_name', nargs=('?' if current else 1),
                      help=old_name_help, default=current)
  parser.add_argument('new_name', help='The new branch name.')

  opts = parser.parse_args(args)

  # when nargs=1, we get a list :(
  if isinstance(opts.old_name, list):
    opts.old_name = opts.old_name[0]

  try:
    run('branch', '-m', opts.old_name, opts.new_name)

    # update the downstreams
    for branch, merge in branch_config_map('merge').iteritems():
      if merge == 'refs/heads/' + opts.old_name:
        # Only care about local branches
        if branch_config(branch, 'remote') == '.':
          set_branch_config(branch, 'merge', 'refs/heads/' + opts.new_name)
  except subprocess2.CalledProcessError as cpe:
    sys.stderr.write(cpe.stderr)
    return 1
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'])
Example #6
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'])
Example #7
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))
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)
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)