summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/tutorial.rst8
-rw-r--r--git/remote.py31
-rw-r--r--git/repo/base.py15
-rw-r--r--git/test/test_git.py16
-rw-r--r--git/test/test_remote.py5
5 files changed, 51 insertions, 24 deletions
diff --git a/doc/source/tutorial.rst b/doc/source/tutorial.rst
index 632d2d0c..7cc296d8 100644
--- a/doc/source/tutorial.rst
+++ b/doc/source/tutorial.rst
@@ -343,6 +343,14 @@ This one sets a custom script to be executed in place of `ssh`, and can be used
with repo.git.custom_environment(GIT_SSH=ssh_executable):
repo.remotes.origin.fetch()
+Here's an example executable that can be used in place of the `ssh_executable` above::
+
+ #!/bin/sh
+ ID_RSA=/var/lib/openshift/5562b947ecdd5ce939000038/app-deployments/id_rsa
+ exec /usr/bin/ssh -o StrictHostKeyChecking=no -i $ID_RSA "$@"
+
+Please note that the script must be executable (i.e. `chomd +x script.sh`). `StrictHostKeyChecking=no` is used to avoid prompts asking to save the hosts key to `~/.ssh/known_hosts`, which happens in case you run this as daemon.
+
You might also have a look at `Git.update_environment(...)` in case you want to setup a changed environment more permanently.
Submodule Handling
diff --git a/git/remote.py b/git/remote.py
index 4baa2838..c9da1979 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -538,7 +538,6 @@ class Remote(LazyMixin, Iterable):
def _get_fetch_info_from_stderr(self, proc, progress):
# skip first line as it is some remote info we are not interested in
- # TODO: Use poll() to process stdout and stderr at same time
output = IterableList('name')
# lines which are no progress are fetch info lines
@@ -551,11 +550,9 @@ class Remote(LazyMixin, Iterable):
progress_handler = progress.new_message_handler()
- for line in proc.stderr:
- line = line.decode(defenc)
- line = line.rstrip()
+ def my_progress_handler(line):
for pline in progress_handler(line):
- if line.startswith('fatal:'):
+ if line.startswith('fatal:') or line.startswith('error:'):
raise GitCommandError(("Error when fetching: %s" % line,), 2)
# END handle special messages
for cmd in cmds:
@@ -568,12 +565,7 @@ class Remote(LazyMixin, Iterable):
# end
# We are only interested in stderr here ...
- try:
- finalize_process(proc)
- except Exception:
- if len(fetch_info_lines) == 0:
- raise
- # end exception handler
+ handle_process_output(proc, None, my_progress_handler, finalize_process)
# read head information
fp = open(join(self.repo.git_dir, 'FETCH_HEAD'), 'rb')
@@ -593,7 +585,6 @@ 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
- # TODO: poll() on file descriptors to know what to read next, process streams concurrently
progress_handler = progress.new_message_handler()
output = IterableList('name')
@@ -613,6 +604,18 @@ class Remote(LazyMixin, Iterable):
raise
return output
+ def _assert_refspec(self):
+ """Turns out we can't deal with remotes if the refspec is missing"""
+ config = self.config_reader
+ try:
+ if config.get_value('fetch', default=type) is type:
+ msg = "Remote '%s' has no refspec set.\n"
+ msg += "You can set it as follows:"
+ msg += " 'git config --add \"remote.%s.fetch +refs/heads/*:refs/heads/*\"'." % self.name
+ raise AssertionError(msg)
+ finally:
+ config.release()
+
def fetch(self, refspec=None, progress=None, **kwargs):
"""Fetch the latest changes for this remote
@@ -640,6 +643,7 @@ class Remote(LazyMixin, Iterable):
:note:
As fetch does not provide progress information to non-ttys, we cannot make
it available here unfortunately as in the 'push' method."""
+ self._assert_refspec()
kwargs = add_progress(kwargs, self.repo.git, progress)
if isinstance(refspec, list):
args = refspec
@@ -647,7 +651,6 @@ class Remote(LazyMixin, Iterable):
args = [refspec]
proc = self.repo.git.fetch(self, *args, with_extended_output=True, as_process=True, v=True, **kwargs)
- proc.stdout.close()
res = self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())
if hasattr(self.repo.odb, 'update_cache'):
self.repo.odb.update_cache()
@@ -661,9 +664,9 @@ class Remote(LazyMixin, Iterable):
:param progress: see 'push' method
:param kwargs: Additional arguments to be passed to git-pull
:return: Please see 'fetch' method """
+ self._assert_refspec()
kwargs = add_progress(kwargs, self.repo.git, progress)
proc = self.repo.git.pull(self, refspec, with_extended_output=True, as_process=True, v=True, **kwargs)
- proc.stdout.close()
res = self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())
if hasattr(self.repo.odb, 'update_cache'):
self.repo.odb.update_cache()
diff --git a/git/repo/base.py b/git/repo/base.py
index c8915bbc..88e21379 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -563,7 +563,8 @@ class Repo(object):
alternates = property(_get_alternates, _set_alternates,
doc="Retrieve a list of alternates paths or set a list paths to be used as alternates")
- def is_dirty(self, index=True, working_tree=True, untracked_files=False):
+ def is_dirty(self, index=True, working_tree=True, untracked_files=False,
+ submodules=True):
"""
:return:
``True``, the repository is considered dirty. By default it will react
@@ -575,7 +576,9 @@ class Repo(object):
return False
# start from the one which is fastest to evaluate
- default_args = ('--abbrev=40', '--full-index', '--raw')
+ default_args = ['--abbrev=40', '--full-index', '--raw']
+ if not submodules:
+ default_args.append('--ignore-submodules')
if index:
# diff index against HEAD
if isfile(self.index.path) and \
@@ -588,7 +591,7 @@ class Repo(object):
return True
# END working tree handling
if untracked_files:
- if len(self.untracked_files):
+ if len(self._get_untracked_files(ignore_submodules=not submodules)):
return True
# END untracked files
return False
@@ -604,10 +607,14 @@ class Repo(object):
:note:
ignored files will not appear here, i.e. files mentioned in .gitignore"""
+ return self._get_untracked_files()
+
+ def _get_untracked_files(self, **kwargs):
# make sure we get all files, no only untracked directores
proc = self.git.status(porcelain=True,
untracked_files=True,
- as_process=True)
+ as_process=True,
+ **kwargs)
# Untracked files preffix in porcelain mode
prefix = "?? "
untracked_files = list()
diff --git a/git/test/test_git.py b/git/test/test_git.py
index 742c842d..a4172f7a 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -192,10 +192,14 @@ class TestGit(TestBase):
rw_repo = Repo.init(os.path.join(rw_dir, 'repo'))
remote = rw_repo.create_remote('ssh-origin', "ssh://git@server/foo")
- with rw_repo.git.custom_environment(GIT_SSH=path):
- try:
- remote.fetch()
- except GitCommandError as err:
- assert 'FOO' in str(err)
+ # This only works if we are not evaluating git-push/pull output in a thread !
+ import select
+ if hasattr(select, 'poll'):
+ with rw_repo.git.custom_environment(GIT_SSH=path):
+ try:
+ remote.fetch()
+ except GitCommandError as err:
+ assert 'FOO' in str(err)
+ # end
# end
- # end
+ # end if select.poll exists
diff --git a/git/test/test_remote.py b/git/test/test_remote.py
index af854988..6c37614d 100644
--- a/git/test/test_remote.py
+++ b/git/test/test_remote.py
@@ -494,6 +494,11 @@ class TestRemote(TestBase):
fetch_info_line_fmt = "c437ee5deb8d00cf02f03720693e4c802e99f390 not-for-merge %s '0.3' of "
fetch_info_line_fmt += "git://github.com/gitpython-developers/GitPython"
remote_info_line_fmt = "* [new branch] nomatter -> %s"
+
+ self.failUnlessRaises(ValueError, FetchInfo._from_line, self.rorepo,
+ remote_info_line_fmt % "refs/something/branch",
+ "269c498e56feb93e408ed4558c8138d750de8893\t\t/Users/ben/test/foo\n")
+
fi = FetchInfo._from_line(self.rorepo,
remote_info_line_fmt % "local/master",
fetch_info_line_fmt % 'remote-tracking branch')