Beispiel #1
0
def _test_delete_archived_branches(target_directory):
    # type: (Text) -> None
    with _run_test(target_directory):
        _initialize_repo()

        # Create all the branches
        make_child_branch("first_branch")
        assert get_current_branch() == "first_branch"

        git("checkout master")

        make_child_branch("second_branch")
        assert get_current_branch() == "second_branch"

        make_child_branch("second_branch_child_one")
        assert get_current_branch() == "second_branch_child_one"

        make_child_branch("second_branch_child_two")
        assert get_current_branch() == "second_branch_child_two"

        git("checkout master")

        with get_branch_tracker() as tracker:
            tracker.set_is_archived("first_branch", True)
            tracker.set_is_archived("second_branch_child_two", True)

        # Test
        delete_archived_branches()

        with get_branch_tracker() as tracker:
            assert not tracker.is_branch_tracked("first_branch")
            assert tracker.is_branch_tracked("second_branch")
            assert tracker.is_branch_tracked("second_branch_child_one")
            assert not tracker.is_branch_tracked("second_branch_child_two")
def rebase_children(is_recursive, extra_git_rebase_args=()):
    # type: (bool, Sequence[Text]) -> None
    current_branch = get_current_branch()
    if extra_git_rebase_args:
        # If the first extra arg starts with "-", "--" must also have been passed, and
        # argparse doesn't remove it for us
        if extra_git_rebase_args[0] == "--":
            extra_git_rebase_args = extra_git_rebase_args[1:]
        extra_args = " " + " ".join(extra_git_rebase_args)
    else:
        extra_args = ""

    with get_branch_tracker() as tracker:
        do_rebase(tracker, tracker.parent_for_child(current_branch),
                  current_branch, extra_args)

        if is_recursive:
            to_rebase_onto = [current_branch]
            while to_rebase_onto:
                parent = to_rebase_onto.pop()
                children = tracker.children_for_parent(parent)
                for child in children:
                    do_rebase(tracker, parent, child, extra_args)
                    to_rebase_onto.append(child)

        # Go back to where we started.
        git("checkout {}".format(current_branch))
Beispiel #3
0
    def run_command(self, args):
        # type: (Namespace) -> None
        extra_arc_land_options = args.arc_land_args
        if extra_arc_land_options:
            # If the first extra arg starts with "-", "--" must also have been passed, and
            # argparse doesn't remove it for us
            if extra_arc_land_options[0] == "--":
                del extra_arc_land_options[0]
            extra_args = " " + " ".join(extra_arc_land_options)
        else:
            extra_args = ""

        current_branch = get_current_branch()
        with get_branch_tracker() as tracker:
            parent = tracker.parent_for_child(current_branch)
            fail_if_not_rebased(current_branch, parent, tracker)

            if parent != "master":
                should_land = raw_input(
                    "Are you sure you want to land onto non-master branch "
                    "'{}'? [y/N] ".format(parent))
                should_land = should_land.lower()
                if should_land not in ("y", "yes"):
                    print "Aborting land"
                    exit()

            arc("land --onto {}{}".format(parent, extra_args))

            # Successfully landed, replace ourselves with our parent
            tracker.collapse_and_remove_parent(current_branch)
def rename_current_branch(new_branch_name):
    # type: (str) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        git("checkout -b %s" % new_branch_name)
        git("branch -d %s" % current_branch)
        tracker.rename_branch(current_branch, new_branch_name)
def rename_current_branch(new_branch_name):
    # type: (Text) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        git("checkout -b {}".format(new_branch_name))
        git("branch -d {}".format(current_branch))
        tracker.rename_branch(current_branch, new_branch_name)
Beispiel #6
0
def _test_clean_branches(target_directory):
    # type: (Text) -> None
    with _run_test(target_directory):
        _initialize_repo()

        # Create all the branches
        make_child_branch("valid_branch")
        assert get_current_branch() == "valid_branch"

        git("checkout master")

        make_child_branch("ghost_branch_childless")
        assert get_current_branch() == "ghost_branch_childless"

        git("checkout master")

        make_child_branch("ghost_branch_with_children")
        assert get_current_branch() == "ghost_branch_with_children"

        make_child_branch("child_of_ghost_branch")
        assert get_current_branch() == "child_of_ghost_branch"

        git("checkout master")

        print("Deleting branches from git")
        git("branch -D ghost_branch_childless")
        git("branch -D ghost_branch_with_children")

        print("Test cleaning by archiving")
        clean_invalid_branches(dry_run=False, archive=True, upstream=False)

        with get_branch_tracker() as tracker:
            assert not tracker.is_archived("valid_branch")
            assert tracker.is_archived("ghost_branch_childless")
            assert tracker.is_archived("ghost_branch_with_children")

            print("Clear archived flags for next test")
            tracker.set_is_archived("ghost_branch_childless", False)
            tracker.set_is_archived("ghost_branch_with_children", False)

        print("Test cleaning by deleting")
        clean_invalid_branches(dry_run=False, archive=False, upstream=False)

        with get_branch_tracker() as tracker:
            assert tracker.is_branch_tracked("valid_branch")
            assert not tracker.is_branch_tracked("ghost_branch_childless")
            assert tracker.is_branch_tracked("ghost_branch_with_children")
def rename_current_branch(new_branch_name, force):
    # type: (Text, bool) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        git("checkout -b {}".format(new_branch_name))
        flag = "-D" if force else "-d"
        git("branch {} {}".format(flag, current_branch))
        tracker.rename_branch(current_branch, new_branch_name)
 def run_command(self, args):
     # type: (Namespace) -> None
     new_parent = args.new_parent
     current_branch = get_current_branch()
     with get_branch_tracker() as tracker:
         tracker.set_parent(current_branch, new_parent)
     print "You may want to rebase on top of the new parent to make sure its changes are " \
           "visible in this branch."
def make_child_branch(new_branch_name):
    # type: (str) -> None
    current_branch = get_current_branch()
    current_rev = hash_for(current_branch)
    with get_branch_tracker() as tracker:
        # Add the child using the current branch as the parent.
        tracker.add_child_for_parent(current_branch, new_branch_name, current_rev)
        # Make the new branch, also where the current branch is
        git("checkout -b %s" % new_branch_name)
Beispiel #10
0
def delete_archived_branches():
    # type: () -> None
    with get_branch_tracker() as tracker:
        for branch in tracker.linearized_branches():
            if tracker.is_branch_tracked(branch) and tracker.is_archived(
                    branch):
                if tracker.children_for_parent(branch):
                    print(
                        "Skipping deletion of archived branch {} because it has children"
                        .format(branch))
                else:
                    print("Deleting {}".format(branch))
                    tracker.remove_child_leaf(branch)
def main(force_remove):
    # type: (bool) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        parent = tracker.parent_for_child(current_branch)
        children = tracker.children_for_parent(current_branch)
        assert not children, "Child branch should not have any children, found %s child(ren)" % len(children)

        git("checkout %s" % parent)
        # This will fail if we're not forcing the remove and the branch isn't merged in.
        delete_flag = "-D" if force_remove else "-d"
        git("branch %s %s" % (delete_flag, current_branch))

        tracker.remove_child_leaf(current_branch)
Beispiel #12
0
def clean_invalid_branches(dry_run, archive, upstream):
    # type: (bool, bool, bool) -> None
    if upstream:
        # Make sure we have latest remote info
        git("fetch --prune")

    with get_branch_tracker() as tracker:
        for branch in tracker.linearized_branches():
            if _is_branch_invalid(tracker, branch, upstream):
                if archive:
                    _archive_invalid_branch(dry_run, tracker, branch)
                else:
                    _delete_invalid_branch_if_possible(dry_run, tracker,
                                                       branch, upstream)
def get_branch_info(branch, use_null_delimiter):
    # type: (Optional[Text], bool) -> Text
    if branch is None:
        branch = get_current_branch()

    with get_branch_tracker() as tracker:
        if not tracker.has_parent(branch):
            sys.exit("Branch does not have a parent: {}".format(branch))
        parent = tracker.parent_for_child(branch)
        base = tracker.base_for_branch(branch)

    if use_null_delimiter:
        return "{}\0{}".format(parent, base)
    else:
        return "Parent branch: {}; Base revision: {}".format(parent, base)
def print_branch_structure():
    # type: () -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        roots = []
        for parent in tracker.get_all_parents():
            if not tracker.has_parent(parent):
                roots.append(parent)

    first = True
    for root in roots:
        if not first:
            print ""
        first = False
        print format_node(current_branch, root)
        print_tree(tracker, current_branch, root, "")
Beispiel #15
0
    def run_command(self, args):
        # type: (Namespace) -> None
        extra_arc_diff_options = args.arc_diff_args
        if extra_arc_diff_options:
            # If the first extra arg starts with "-", "--" must also have been passed, and
            # argparse doesn't remove it for us
            if extra_arc_diff_options[0] == "--":
                del extra_arc_diff_options[0]
            extra_args = " " + " ".join(extra_arc_diff_options)
        else:
            extra_args = ""

        current_branch = get_current_branch()
        with get_branch_tracker() as tracker:
            base = tracker.base_for_branch(current_branch)
            arc("diff {}{}".format(base, extra_args))
def get_branch_structure_string(show_all):
    # type: (bool) -> str
    current_branch = get_current_branch()
    structure_parts = []  # type: List[str]
    with get_branch_tracker() as tracker:
        roots = []
        for parent in tracker.get_all_parents():
            if not tracker.has_parent(parent):
                roots.append(parent)

        skipped_archived = _get_branch_structure_parts_internal(
            tracker, current_branch, roots, structure_parts, show_all)

        if skipped_archived:
            structure_parts.append("(not displaying archived branches, run with --all to see them)")

    return "\n".join(structure_parts)
def rebase_children(is_recursive):
    # type: (bool) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        do_rebase(tracker, tracker.parent_for_child(current_branch), current_branch)

        if is_recursive:
            to_rebase_onto = [current_branch]
            while to_rebase_onto:
                parent = to_rebase_onto.pop()
                children = tracker.children_for_parent(parent)
                for child in children:
                    do_rebase(tracker, parent, child)
                    to_rebase_onto.append(child)

        # Go back to where we started.
        git("checkout %s" % current_branch)
Beispiel #18
0
def rebase_children(is_recursive):
    # type: (bool) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        do_rebase(tracker, tracker.parent_for_child(current_branch), current_branch)

        if is_recursive:
            to_rebase_onto = [current_branch]
            while to_rebase_onto:
                parent = to_rebase_onto.pop()
                children = tracker.children_for_parent(parent)
                for child in children:
                    do_rebase(tracker, parent, child)
                    to_rebase_onto.append(child)

        # Go back to where we started.
        git("checkout {}".format(current_branch))
def main():
    # type: () -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        parent = tracker.parent_for_child(current_branch)
        fail_if_not_rebased(current_branch, parent, tracker)

        if parent != "master":
            should_land = raw_input("Are you sure you want to land onto non-master branch '%s'? [y/N] " % parent)
            should_land = should_land.lower()
            if should_land not in ("y", "yes"):
                print "Aborting land"
                exit()

        arc("land --onto %s" % parent)

        # Successfully landed, replace ourselves with our parent
        tracker.collapse_and_remove_parent(current_branch)
def get_branch_structure_string(show_all):
    # type: (bool) -> Text
    current_branch = get_current_branch()
    structure_parts = []  # type: List[Text]
    with get_branch_tracker() as tracker:
        roots = []
        for parent in tracker.get_all_parents():
            if not tracker.has_parent(parent):
                roots.append(parent)
        roots = sorted(roots)

        skipped_archived = _get_branch_structure_parts_internal(
            tracker, current_branch, roots, structure_parts, show_all)

        if skipped_archived:
            structure_parts.append("(not displaying archived branches, run with --all to see them)")

    return "\n".join(structure_parts)
def remove_branch(force_remove):
    # type: (bool) -> None
    current_branch = get_current_branch()
    current_commit = hash_for(current_branch)
    with get_branch_tracker() as tracker:
        parent = tracker.parent_for_child(current_branch)
        children = tracker.children_for_parent(current_branch)
        assert not children, \
            "Child branch should not have any children, found {} child(ren)".format(len(children))

        merged_into_parent = [
            line[2:]
            for line in git("branch --merged {}".format(parent)).split('\n')
            if line
        ]
        if current_branch in merged_into_parent:
            print("Removing merged branch {!r} (was at commit {})".format(
                current_branch, current_commit))
        elif force_remove:
            print("Force removing unmerged branch {!r} (was at commit {})".
                  format(
                      current_branch,
                      current_commit,
                  ))
        else:
            print("")
            print("!!!!!!!!")
            print("!!! Trying to remove branch {!r} not merged into its parent. Re-run with" \
                  "".format(current_branch))
            print(
                "!!! '--force' if you want to force the deletion of this branch."
            )
            print("!!!")
            print("!!! WARNING: Running with '--force' may cause data loss")
            print("!!!!!!!!")
            print("")
            exit(1)

        git("checkout {}".format(parent))
        # This will fail if we're not forcing the remove and the branch isn't merged in.
        delete_flag = "-D" if force_remove else "-d"
        git("branch {} {}".format(delete_flag, current_branch))

        tracker.remove_child_leaf(current_branch)
def make_child_branch(new_branch_name, revision=None):
    # type: (Text, Optional[Text]) -> None
    parent = get_current_branch()
    if revision is None:
        # Use the current revision as the base
        base_rev = hash_for("HEAD")
    else:
        # Use the merge-base of the given revision and the parent branch as the base
        base_rev = git("merge-base {} {}".format(parent, revision)).strip()

    with get_branch_tracker() as tracker:
        # Add the child using the current branch as the parent.
        tracker.add_child_for_parent(parent, new_branch_name, base_rev)
        # Make the new branch, either where the current branch is or at the specified revision
        if revision is None:
            command = "checkout -b {}".format(new_branch_name)
        else:
            command = "checkout -b {} {}".format(new_branch_name, revision)
        git(command)
def set_archived(archived, branch_name=None):
    # type: (bool, Optional[str]) -> None
    if branch_name is None:
        branch_name = get_current_branch()
    with get_branch_tracker() as tracker:
        tracker.set_is_archived(branch_name, archived)
 def run_command(self, args):
     # type: (Namespace) -> None
     with get_branch_tracker() as tracker:
         remove_branch(tracker,
                       branch_name=args.branch_name or get_current_branch(),
                       force_remove=args.force)
def main(new_parent):
    # type: (str) -> None
    current_branch = get_current_branch()
    with get_branch_tracker() as tracker:
        tracker.set_parent(current_branch, new_parent)
    print "You may want to rebase on top of the new parent to make sure its changes are visible in this branch."
def set_archived(archived, branch_name=None):
    # type: (bool, Optional[str]) -> None
    if branch_name is None:
        branch_name = get_current_branch()
    with get_branch_tracker() as tracker:
        tracker.set_is_archived(branch_name, archived)