|
@@ -8,7 +8,7 @@ from __future__ import print_function |
|
|
import os |
|
|
import os |
|
|
|
|
|
|
|
|
from colorama import Fore, Style |
|
|
from colorama import Fore, Style |
|
|
from git import Repo, exc |
|
|
|
|
|
|
|
|
from git import RemoteReference as RemoteRef, Repo, exc |
|
|
from git.util import RemoteProgress |
|
|
from git.util import RemoteProgress |
|
|
|
|
|
|
|
|
__all__ = ["update_bookmarks", "update_directories"] |
|
|
__all__ = ["update_bookmarks", "update_directories"] |
|
@@ -26,25 +26,21 @@ ERROR = RED + "Error:" + RESET |
|
|
class _ProgressMonitor(RemoteProgress): |
|
|
class _ProgressMonitor(RemoteProgress): |
|
|
"""Displays relevant output during the fetching process.""" |
|
|
"""Displays relevant output during the fetching process.""" |
|
|
|
|
|
|
|
|
def __init__(self, verbose): |
|
|
|
|
|
|
|
|
def __init__(self): |
|
|
super(_ProgressMonitor, self).__init__() |
|
|
super(_ProgressMonitor, self).__init__() |
|
|
self._verbose = verbose |
|
|
|
|
|
|
|
|
|
|
|
def update(self, op_code, cur_count, max_count=None, message=''): |
|
|
def update(self, op_code, cur_count, max_count=None, message=''): |
|
|
"""Called whenever progress changes. Overrides default behavior.""" |
|
|
"""Called whenever progress changes. Overrides default behavior.""" |
|
|
if self._verbose: |
|
|
|
|
|
if op_code & self.COUNTING: |
|
|
|
|
|
print(" ({0})".format(cur_count), end="") |
|
|
|
|
|
elif op_code & (self.COMPRESSING | self.RECEIVING): |
|
|
|
|
|
if op_code & self.BEGIN: |
|
|
|
|
|
print("\b, ", end="") |
|
|
|
|
|
if op_code & self.END: |
|
|
|
|
|
end = ")" |
|
|
|
|
|
else: |
|
|
|
|
|
end = "\b" * (1 + len(cur_count) + len(max_count)) |
|
|
|
|
|
print("{0}/{1}".format(cur_count, max_count), end=end) |
|
|
|
|
|
elif op_code & self.BEGIN: |
|
|
|
|
|
print(".", end="") |
|
|
|
|
|
|
|
|
if op_code & self.COUNTING: |
|
|
|
|
|
print(" ({0})".format(cur_count), end="") |
|
|
|
|
|
elif op_code & (self.COMPRESSING | self.RECEIVING): |
|
|
|
|
|
if op_code & self.BEGIN: |
|
|
|
|
|
print("\b, ", end="") |
|
|
|
|
|
if op_code & self.END: |
|
|
|
|
|
end = ")" |
|
|
|
|
|
else: |
|
|
|
|
|
end = "\b" * (1 + len(cur_count) + len(max_count)) |
|
|
|
|
|
print("{0}/{1}".format(cur_count, max_count), end=end) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _Stasher(object): |
|
|
class _Stasher(object): |
|
@@ -75,32 +71,30 @@ def _read_config(repo, attr): |
|
|
except exc.GitCommandError: |
|
|
except exc.GitCommandError: |
|
|
return None |
|
|
return None |
|
|
|
|
|
|
|
|
def _format_fetch_result(results): |
|
|
|
|
|
"""Format and print the results of a verbose fetch.""" |
|
|
|
|
|
info = [("NEW_HEAD", "new branches"), ("NEW_TAG", "new tags"), |
|
|
|
|
|
("FAST_FORWARD", "updates"), ("ERROR", "errors")] |
|
|
|
|
|
rlist = [] |
|
|
|
|
|
for attr, desc in info: |
|
|
|
|
|
names = [res.name for res in results if res.flags & getattr(res, attr)] |
|
|
|
|
|
if names: |
|
|
|
|
|
rlist.append("{0} ({1})".format(desc, ", ".join(names))) |
|
|
|
|
|
print(":", (", ".join(rlist) if rlist else "up to date") + ".") |
|
|
|
|
|
|
|
|
|
|
|
def _fetch_remotes(remotes, verbose): |
|
|
|
|
|
|
|
|
def _fetch_remotes(remotes): |
|
|
"""Fetch a list of remotes, displaying progress info along the way.""" |
|
|
"""Fetch a list of remotes, displaying progress info along the way.""" |
|
|
if verbose: |
|
|
|
|
|
for remote in remotes: |
|
|
|
|
|
print(INDENT2, "Fetching", remote.name, end="") |
|
|
|
|
|
result = remote.fetch(progress=_ProgressMonitor(True)) |
|
|
|
|
|
_format_fetch_result(result) |
|
|
|
|
|
else: |
|
|
|
|
|
print(INDENT2, "Fetching:", end=" ") |
|
|
|
|
|
for i, remote in enumerate(remotes): |
|
|
|
|
|
print(remote.name, end="") |
|
|
|
|
|
remote.fetch(progress=_ProgressMonitor(False)) |
|
|
|
|
|
if i < len(remotes) - 1: |
|
|
|
|
|
print(", ", end="") |
|
|
|
|
|
print(".") |
|
|
|
|
|
|
|
|
def _get_name(ref): |
|
|
|
|
|
"""Return the local name of a remote or tag reference.""" |
|
|
|
|
|
return ref.remote_head if isinstance(ref, RemoteRef) else ref.name |
|
|
|
|
|
|
|
|
|
|
|
info = [("NEW_HEAD", "new branch", "new branches"), |
|
|
|
|
|
("NEW_TAG", "new tag", "new tags"), |
|
|
|
|
|
("FAST_FORWARD", "branch update", "branch updates"), |
|
|
|
|
|
("ERROR", "error", "errors")] |
|
|
|
|
|
up_to_date = BLUE + "up to date" + RESET |
|
|
|
|
|
|
|
|
|
|
|
for remote in remotes: |
|
|
|
|
|
print(INDENT2, "Fetching", BOLD + remote.name, end="") |
|
|
|
|
|
results = remote.fetch(progress=_ProgressMonitor()) |
|
|
|
|
|
rlist = [] |
|
|
|
|
|
for attr, singular, plural in info: |
|
|
|
|
|
names = [_get_name(res.ref) |
|
|
|
|
|
for res in results if res.flags & getattr(res, attr)] |
|
|
|
|
|
if names: |
|
|
|
|
|
desc = singular if len(names) == 1 else plural |
|
|
|
|
|
colored = GREEN + desc + RESET |
|
|
|
|
|
rlist.append("{0} ({1})".format(colored, ", ".join(names))) |
|
|
|
|
|
print(":", (", ".join(rlist) if rlist else up_to_date) + ".") |
|
|
|
|
|
|
|
|
def _is_up_to_date(repo, branch, upstream): |
|
|
def _is_up_to_date(repo, branch, upstream): |
|
|
"""Return whether *branch* is up-to-date with its *upstream*.""" |
|
|
"""Return whether *branch* is up-to-date with its *upstream*.""" |
|
@@ -171,8 +165,7 @@ def _update_branch(repo, branch, merge, rebase, stasher=None): |
|
|
else: |
|
|
else: |
|
|
_merge(repo, upstream.name) |
|
|
_merge(repo, upstream.name) |
|
|
|
|
|
|
|
|
def _update_repository(repo, current_only=False, rebase=False, merge=False, |
|
|
|
|
|
verbose=False): |
|
|
|
|
|
|
|
|
def _update_repository(repo, current_only=False, rebase=False, merge=False): |
|
|
"""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 |
|
@@ -180,8 +173,7 @@ def _update_repository(repo, current_only=False, rebase=False, merge=False, |
|
|
current branch if ``True``. By default, we will merge unless |
|
|
current branch if ``True``. By default, we will merge unless |
|
|
``pull.rebase`` or ``branch.<name>.rebase`` is set in config; *rebase* will |
|
|
``pull.rebase`` or ``branch.<name>.rebase`` is set in config; *rebase* will |
|
|
cause us to always rebase with ``--preserve-merges``, and *merge* will |
|
|
cause us to always rebase with ``--preserve-merges``, and *merge* will |
|
|
cause us to always merge. If *verbose* is set, additional information is |
|
|
|
|
|
printed out for the user. |
|
|
|
|
|
|
|
|
cause us to always merge. |
|
|
""" |
|
|
""" |
|
|
print(INDENT1, BOLD + os.path.split(repo.working_dir)[1] + ":") |
|
|
print(INDENT1, BOLD + os.path.split(repo.working_dir)[1] + ":") |
|
|
|
|
|
|
|
@@ -197,8 +189,7 @@ def _update_repository(repo, current_only=False, rebase=False, merge=False, |
|
|
if not remotes: |
|
|
if not remotes: |
|
|
print(INDENT2, ERROR, "no remotes configured to pull from.") |
|
|
print(INDENT2, ERROR, "no remotes configured to pull from.") |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
_fetch_remotes(remotes, verbose) |
|
|
|
|
|
|
|
|
_fetch_remotes(remotes) |
|
|
|
|
|
|
|
|
rebase = rebase or _read_config(repo, "pull.rebase") |
|
|
rebase = rebase or _read_config(repo, "pull.rebase") |
|
|
_update_branch(repo, active, merge, rebase) |
|
|
_update_branch(repo, active, merge, rebase) |
|
|