summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjez <jezreel@gmail.com>2011-05-21 10:13:45 +0000
committerSebastian Thiel <byronimo@gmail.com>2011-06-07 21:11:11 +0200
commit863b386e195bb2b609b25614f732b1b502bc79a4 (patch)
tree78630d2680d4d47fc2b4d8451b8f46f45b9e77ae
parentdfe3ba3e5c08ee88afe89cc331081bbfbf5520e0 (diff)
downloadgitpython-863b386e195bb2b609b25614f732b1b502bc79a4.tar.gz
Add progress tracking for git-clone.
-rw-r--r--git/remote.py50
-rw-r--r--git/repo/base.py23
-rw-r--r--git/util.py34
3 files changed, 60 insertions, 47 deletions
diff --git a/git/remote.py b/git/remote.py
index d3639f7b..6f44837b 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -24,7 +24,11 @@ from refs import (
TagReference
)
-from git.util import join_path
+from git.util import (
+ join_path,
+ _digest_process_messages,
+ _finalize_proc
+ )
from gitdb.util import join
import re
@@ -432,42 +436,6 @@ class Remote(LazyMixin, Iterable):
self.repo.git.remote("update", self.name)
return self
- def _digest_process_messages(self, fh, progress):
- """Read progress messages from file-like object fh, supplying the respective
- progress messages to the progress instance.
-
- :return: list(line, ...) list of lines without linebreaks that did
- not contain progress information"""
- line_so_far = ''
- dropped_lines = list()
- while True:
- char = fh.read(1)
- if not char:
- break
-
- if char in ('\r', '\n'):
- dropped_lines.extend(progress._parse_progress_line(line_so_far))
- line_so_far = ''
- else:
- line_so_far += char
- # END process parsed line
- # END while file is not done reading
- return dropped_lines
-
-
- def _finalize_proc(self, proc):
- """Wait for the process (fetch, pull or push) and handle its errors accordingly"""
- try:
- proc.wait()
- except GitCommandError,e:
- # if a push has rejected items, the command has non-zero return status
- # a return status of 128 indicates a connection error - reraise the previous one
- if proc.poll() == 128:
- raise
- pass
- # END exception handling
-
-
def _get_fetch_info_from_stderr(self, proc, progress):
# skip first line as it is some remote info we are not interested in
output = IterableList('name')
@@ -477,7 +445,7 @@ class Remote(LazyMixin, Iterable):
# this also waits for the command to finish
# Skip some progress lines that don't provide relevant information
fetch_info_lines = list()
- for line in self._digest_process_messages(proc.stderr, progress):
+ for line in _digest_process_messages(proc.stderr, progress):
if line.startswith('From') or line.startswith('remote: Total'):
continue
elif line.startswith('warning:'):
@@ -499,7 +467,7 @@ class Remote(LazyMixin, Iterable):
output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
for err_line,fetch_line in zip(fetch_info_lines, fetch_head_info))
- self._finalize_proc(proc)
+ _finalize_proc(proc)
return output
def _get_push_info(self, proc, progress):
@@ -507,7 +475,7 @@ class Remote(LazyMixin, Iterable):
# we hope stdout can hold all the data, it should ...
# read the lines manually as it will use carriage returns between the messages
# to override the previous one. This is why we read the bytes manually
- self._digest_process_messages(proc.stderr, progress)
+ _digest_process_messages(proc.stderr, progress)
output = IterableList('name')
for line in proc.stdout.readlines():
@@ -519,7 +487,7 @@ class Remote(LazyMixin, Iterable):
# END exception handling
# END for each line
- self._finalize_proc(proc)
+ _finalize_proc(proc)
return output
diff --git a/git/repo/base.py b/git/repo/base.py
index 0405a5f9..55aec05b 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -18,6 +18,11 @@ from git.db import (
)
+from git.util import (
+ _digest_process_messages,
+ _finalize_proc
+ )
+
from gitdb.util import (
join,
isfile,
@@ -652,7 +657,7 @@ class Repo(object):
return Repo(path)
@classmethod
- def _clone(cls, git, url, path, odb_default_type, **kwargs):
+ def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
# 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
@@ -679,7 +684,10 @@ class Repo(object):
# END windows handling
try:
- git.clone(url, path, **kwargs)
+ proc = git.clone(url, path, with_extended_output=True, as_process=True, v=True, progress=True, **kwargs)
+ if progress:
+ _digest_process_messages(proc.stderr, progress)
+ _finalize_proc(proc)
finally:
if prev_cwd is not None:
os.chdir(prev_cwd)
@@ -703,11 +711,13 @@ class Repo(object):
# END handle remote repo
return repo
- def clone(self, path, **kwargs):
+ def clone(self, path, progress=None, **kwargs):
"""Create a clone from this repository.
:param path:
is the full path of the new repo (traditionally ends with ./<name>.git).
+ :param progress: See 'git.remote.Remote.push'.
+
:param kwargs:
odbt = ObjectDatabase Type, allowing to determine the object database
implementation used by the returned Repo instance
@@ -715,16 +725,17 @@ class Repo(object):
All remaining keyword arguments are given to the git-clone command
:return: ``git.Repo`` (the newly cloned repo)"""
- return self._clone(self.git, self.git_dir, path, type(self.odb), **kwargs)
+ return self._clone(self.git, self.git_dir, path, type(self.odb), progress, **kwargs)
@classmethod
- def clone_from(cls, url, to_path, **kwargs):
+ def clone_from(cls, url, to_path, progress=None, **kwargs):
"""Create a clone from the given URL
:param url: valid git url, see http://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS
:param to_path: Path to which the repository should be cloned to
+ :param progress: See 'git.remote.Remote.push'.
:param kwargs: see the ``clone`` method
:return: Repo instance pointing to the cloned directory"""
- return cls._clone(Git(os.getcwd()), url, to_path, GitCmdObjectDB, **kwargs)
+ return cls._clone(Git(os.getcwd()), url, to_path, GitCmdObjectDB, progress, **kwargs)
def archive(self, ostream, treeish=None, prefix=None, **kwargs):
"""Archive the tree at the given revision.
diff --git a/git/util.py b/git/util.py
index 7cbef07f..b3a420b3 100644
--- a/git/util.py
+++ b/git/util.py
@@ -100,6 +100,40 @@ def get_user_id():
# END get username from login
return "%s@%s" % (username, platform.node())
+def _digest_process_messages(fh, progress):
+ """Read progress messages from file-like object fh, supplying the respective
+ progress messages to the progress instance.
+
+ :return: list(line, ...) list of lines without linebreaks that did
+ not contain progress information"""
+ line_so_far = ''
+ dropped_lines = list()
+ while True:
+ char = fh.read(1)
+ if not char:
+ break
+
+ if char in ('\r', '\n'):
+ dropped_lines.extend(progress._parse_progress_line(line_so_far))
+ line_so_far = ''
+ else:
+ line_so_far += char
+ # END process parsed line
+ # END while file is not done reading
+ return dropped_lines
+
+def _finalize_proc(proc):
+ """Wait for the process (clone, fetch, pull or push) and handle its errors accordingly"""
+ try:
+ proc.wait()
+ except GitCommandError,e:
+ # if a push has rejected items, the command has non-zero return status
+ # a return status of 128 indicates a connection error - reraise the previous one
+ if proc.poll() == 128:
+ raise
+ pass
+ # END exception handling
+
#} END utilities
#{ Classes