Browse Source

Added --prune to remove deleted remote-tracking branches (closes #18)

tags/v0.4
Ben Kurtovic 9 years ago
parent
commit
ae8e441d39
4 changed files with 23 additions and 7 deletions
  1. +2
    -0
      CHANGELOG
  2. +4
    -0
      README.md
  3. +4
    -1
      gitup/script.py
  4. +13
    -6
      gitup/update.py

+ 2
- 0
CHANGELOG View File

@@ -1,5 +1,7 @@
v0.3.1 (unreleased): v0.3.1 (unreleased):


- Added a `--prune` flag to delete remote-tracking branches that no longer
exist on their remote after fetching.
- Fixed a bug related to Python 3 compatibility. - Fixed a bug related to Python 3 compatibility.


v0.3 (released June 7, 2015): v0.3 (released June 7, 2015):


+ 4
- 0
README.md View File

@@ -89,6 +89,10 @@ upstreams configured. It will always skip branches where this is not possible
(e.g. dirty working directory or a merge/rebase is required). Pass (e.g. dirty working directory or a merge/rebase is required). Pass
`--fetch-only` (or `-f`) to only fetch remotes. `--fetch-only` (or `-f`) to only fetch remotes.


After fetching, gitup will _keep_ remote-tracking branches that no longer exist
upstream. Pass `--prune` (or `-p`) to delete them, or set `fetch.prune` or
`remote.<name>.prune` in git config to do this by default.

For a full list of all command arguments and abbreviations: For a full list of all command arguments and abbreviations:


gitup --help gitup --help


+ 4
- 1
gitup/script.py View File

@@ -41,6 +41,9 @@ def main():
group_u.add_argument( group_u.add_argument(
'-f', '--fetch-only', action="store_true", '-f', '--fetch-only', action="store_true",
help="only fetch remotes, don't try to fast-forward any branches") help="only fetch remotes, don't try to fast-forward any branches")
group_u.add_argument(
'-p', '--prune', action="store_true", help="""after fetching, delete
remote-tracking branches that no longer exist on their remote""")


group_b.add_argument( group_b.add_argument(
'-a', '--add', dest="bookmarks_to_add", nargs="+", metavar="path", '-a', '--add', dest="bookmarks_to_add", nargs="+", metavar="path",
@@ -66,7 +69,7 @@ def main():


color_init(autoreset=True) color_init(autoreset=True)
args = parser.parse_args() args = parser.parse_args()
update_args = args.current_only, args.fetch_only
update_args = args.current_only, args.fetch_only, args.prune


print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater") print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater")
print() print()


+ 13
- 6
gitup/update.py View File

@@ -53,12 +53,13 @@ class _ProgressMonitor(RemoteProgress):
print(str(cur_count), end=end) print(str(cur_count), end=end)




def _fetch_remotes(remotes):
def _fetch_remotes(remotes, prune):
"""Fetch a list of remotes, displaying progress info along the way.""" """Fetch a list of remotes, displaying progress info along the way."""
def _get_name(ref): def _get_name(ref):
"""Return the local name of a remote or tag reference.""" """Return the local name of a remote or tag reference."""
return ref.remote_head if isinstance(ref, RemoteRef) else ref.name return ref.remote_head if isinstance(ref, RemoteRef) else ref.name


# TODO: missing branch deleted (via --prune):
info = [("NEW_HEAD", "new branch", "new branches"), info = [("NEW_HEAD", "new branch", "new branches"),
("NEW_TAG", "new tag", "new tags"), ("NEW_TAG", "new tag", "new tags"),
("FAST_FORWARD", "branch update", "branch updates")] ("FAST_FORWARD", "branch update", "branch updates")]
@@ -72,7 +73,7 @@ def _fetch_remotes(remotes):
continue continue


try: try:
results = remote.fetch(progress=_ProgressMonitor())
results = remote.fetch(progress=_ProgressMonitor(), prune=prune)
except exc.GitCommandError as err: except exc.GitCommandError as err:
msg = err.command[0].replace("Error when fetching: ", "") msg = err.command[0].replace("Error when fetching: ", "")
if not msg.endswith("."): if not msg.endswith("."):
@@ -101,12 +102,16 @@ def _update_branch(repo, branch, is_active=False):
if not upstream: if not upstream:
print(YELLOW + "skipped:", "no upstream is tracked.") print(YELLOW + "skipped:", "no upstream is tracked.")
return return

try: try:
branch.commit, upstream.commit
branch.commit
except ValueError: except ValueError:
print(YELLOW + "skipped:", "branch has no revisions.") print(YELLOW + "skipped:", "branch has no revisions.")
return return
try:
upstream.commit
except ValueError:
print(YELLOW + "skipped:", "upstream does not exist.")
return


base = repo.git.merge_base(branch.commit, upstream.commit) base = repo.git.merge_base(branch.commit, upstream.commit)
if repo.commit(base) == upstream.commit: if repo.commit(base) == upstream.commit:
@@ -133,13 +138,15 @@ def _update_branch(repo, branch, is_active=False):
repo.git.branch(branch.name, upstream.name, force=True) repo.git.branch(branch.name, upstream.name, force=True)
print(GREEN + "done", end=".\n") print(GREEN + "done", end=".\n")


def _update_repository(repo, current_only=False, fetch_only=False):
def _update_repository(repo, current_only, fetch_only, prune):
"""Update a single git repository by fetching remotes and rebasing/merging. """Update a single git repository by fetching remotes and rebasing/merging.


The specific actions depend on the arguments given. We will fetch all The specific actions depend on the arguments given. We will fetch all
remotes if *current_only* is ``False``, or only the remote tracked by the remotes if *current_only* is ``False``, or only the remote tracked by the
current branch if ``True``. If *fetch_only* is ``False``, we will also current branch if ``True``. If *fetch_only* is ``False``, we will also
update all fast-forwardable branches that are tracking valid upstreams. update all fast-forwardable branches that are tracking valid upstreams.
If *prune* is ``True``, remote-tracking branches that no longer exist on
their remote after fetching will be deleted.
""" """
print(INDENT1, BOLD + os.path.split(repo.working_dir)[1] + ":") print(INDENT1, BOLD + os.path.split(repo.working_dir)[1] + ":")


@@ -163,7 +170,7 @@ def _update_repository(repo, current_only=False, fetch_only=False):
if not remotes: if not remotes:
print(INDENT2, ERROR, "no remotes configured to fetch.") print(INDENT2, ERROR, "no remotes configured to fetch.")
return return
_fetch_remotes(remotes)
_fetch_remotes(remotes, prune)


if not fetch_only: if not fetch_only:
for branch in sorted(repo.heads, key=lambda b: b.name): for branch in sorted(repo.heads, key=lambda b: b.name):


Loading…
Cancel
Save