From b4492c7965cd8e3c5faaf28b2a6414b04984720b Mon Sep 17 00:00:00 2001 From: Barry Scott Date: Sat, 28 May 2016 12:05:23 +0100 Subject: The progress arg to push, pull, fetch and clone is now a python callable. This simplifies the API and removes the parser, RemoteProgres, from the API as RemoteProgress is an internal detail of the implementation. progress is accepted as: * None - drop progress messages * callable (function etc) - call the function with the same args as update * object - assume its RemoteProgress derived as use as before RemoteProgress takes an optional progress_function argument. It will call the progress function if not None otherwise call self.update as it used to. --- git/remote.py | 47 ++++++++++++++++++++++++++++++++++++++++++----- git/repo/base.py | 5 ++++- git/util.py | 12 ++++++++---- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/git/remote.py b/git/remote.py index e430abf5..320d4e56 100644 --- a/git/remote.py +++ b/git/remote.py @@ -57,6 +57,22 @@ def add_progress(kwargs, git, progress): #} END utilities +def progress_object(progress): + """Given the 'progress' return a suitable object derived from + RemoteProgress(). + """ + # new API only needs progress as a function + if callable(progress): + return RemoteProgress(progress) + + # where None is passed create a parser that eats the progress + elif progress is None: + return RemoteProgress() + + # assume its the old API with an instance of RemoteProgress. + else: + return progress + class PushInfo(object): @@ -535,7 +551,10 @@ class Remote(LazyMixin, Iterable): self.repo.git.remote(scmd, self.name, **kwargs) return self + def _get_fetch_info_from_stderr(self, proc, progress): + progress = progress_object(progress) + # skip first line as it is some remote info we are not interested in output = IterableList('name') @@ -580,6 +599,8 @@ class Remote(LazyMixin, Iterable): return output def _get_push_info(self, proc, progress): + progress = progress_object(progress) + # read progress information from stderr # we hope stdout can hold all the data, it should ... # read the lines manually as it will use carriage returns between the messages @@ -654,7 +675,7 @@ class Remote(LazyMixin, Iterable): proc = self.repo.git.fetch(self, *args, as_process=True, with_stdout=False, v=True, **kwargs) - res = self._get_fetch_info_from_stderr(proc, progress or RemoteProgress()) + res = self._get_fetch_info_from_stderr(proc, progress) if hasattr(self.repo.odb, 'update_cache'): self.repo.odb.update_cache() return res @@ -672,7 +693,7 @@ class Remote(LazyMixin, Iterable): self._assert_refspec() kwargs = add_progress(kwargs, self.repo.git, progress) proc = self.repo.git.pull(self, refspec, with_stdout=False, as_process=True, v=True, **kwargs) - res = self._get_fetch_info_from_stderr(proc, progress or RemoteProgress()) + res = self._get_fetch_info_from_stderr(proc, progress) if hasattr(self.repo.odb, 'update_cache'): self.repo.odb.update_cache() return res @@ -682,10 +703,26 @@ class Remote(LazyMixin, Iterable): :param refspec: see 'fetch' method :param progress: - Instance of type RemoteProgress allowing the caller to receive - progress information until the method returns. If None, progress information will be discarded + No further progress information is returned after push returns. + + A function (callable) that is called with the progress infomation: + + progress( op_code, cur_count, max_count=None, message='' ) + + op_code is a bit mask of values defined in git.RemoteProgress + + cur_count and max_count are float values. + + max_count is None if there is no max_count + + messages is '' if there is no additon message. + + Deprecated: Pass in a class derived from git.RemoteProgres that + overrides the update() function. + + :param kwargs: Additional arguments to be passed to git-push :return: IterableList(PushInfo, ...) iterable list of PushInfo instances, each @@ -697,7 +734,7 @@ class Remote(LazyMixin, Iterable): be null.""" kwargs = add_progress(kwargs, self.repo.git, progress) proc = self.repo.git.push(self, refspec, porcelain=True, as_process=True, **kwargs) - return self._get_push_info(proc, progress or RemoteProgress()) + return self._get_push_info(proc, progress) @property def config_reader(self): diff --git a/git/repo/base.py b/git/repo/base.py index bc5a7c35..9ba2b1d2 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -32,7 +32,8 @@ from git.index import IndexFile from git.config import GitConfigParser from git.remote import ( Remote, - add_progress + add_progress, + progress_object ) from git.db import GitCmdObjectDB @@ -872,6 +873,8 @@ class Repo(object): @classmethod def _clone(cls, git, url, path, odb_default_type, progress, **kwargs): + progress = progress_object(progress) + # special handling for windows for path at which the clone should be # created. # tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence diff --git a/git/util.py b/git/util.py index a267f183..9b86b191 100644 --- a/git/util.py +++ b/git/util.py @@ -174,11 +174,16 @@ class RemoteProgress(object): DONE_TOKEN = 'done.' TOKEN_SEPARATOR = ', ' - __slots__ = ("_cur_line", "_seen_ops") + __slots__ = ("_cur_line", "_seen_ops", "__progress_function") re_op_absolute = re.compile(r"(remote: )?([\w\s]+):\s+()(\d+)()(.*)") re_op_relative = re.compile(r"(remote: )?([\w\s]+):\s+(\d+)% \((\d+)/(\d+)\)(.*)") - def __init__(self): + def __init__(self, progress_function=None): + if progress_function is not None: + self.__progress_function = progress_function + else: + self.__progress_function = self.update + self._seen_ops = list() self._cur_line = None @@ -267,7 +272,7 @@ class RemoteProgress(object): # END end message handling message = message.strip(self.TOKEN_SEPARATOR) - self.update(op_code, + self.__progress_function(op_code, cur_count and float(cur_count), max_count and float(max_count), message) @@ -314,7 +319,6 @@ class RemoteProgress(object): You may read the contents of the current line in self._cur_line""" pass - class Actor(object): """Actors hold information about a person acting on the repository. They -- cgit v1.2.1