summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/index.py81
1 files changed, 61 insertions, 20 deletions
diff --git a/lib/git/index.py b/lib/git/index.py
index 0a7bfe6e..f0da4b64 100644
--- a/lib/git/index.py
+++ b/lib/git/index.py
@@ -29,13 +29,18 @@ class CheckoutError( Exception ):
changes.
The .failed_files attribute contains a list of relative paths that failed
- to be checked out as they contained changes that did not exist in the index"""
- def __init__(self, message, failed_files):
- super(CheckoutError, self).__init__(message)
+ to be checked out as they contained changes that did not exist in the index.
+
+ The .valid_files attribute contains a list of relative paths to files that
+ were checked out successfully and hence match the version stored in the
+ index"""
+ def __init__(self, message, failed_files, valid_files):
+ Exception.__init__(self, message)
self.failed_files = failed_files
+ self.valid_files = valid_files
def __str__(self):
- return super(CheckoutError, self).__str__() + ":%s" % self.failed_files
+ return Exception.__str__(self) + ":%s" % self.failed_files
class _TemporaryFileSwap(object):
@@ -1009,29 +1014,34 @@ class IndexFile(LazyMixin, diff.Diffable):
@default_index
def checkout(self, paths=None, force=False, fprogress=lambda *args: None, **kwargs):
"""
- Checkout the given paths or all files from the version in the index.
+ Checkout the given paths or all files from the version known to the index into
+ the working tree.
``paths``
If None, all paths in the index will be checked out. Otherwise an iterable
- of relative or absolute paths or a single path pointing to files in the index
- is expected.
- The command will raise of files do not exist in the index ( as opposed to the
- original git command who ignores them )
- The provided progress information will contain None as path and item if no
- explicit paths are given.
+ of relative or absolute paths or a single path pointing to files or directories
+ in the index is expected.
+ The command will raise of files or directories do not exist in the index
+ ( as opposed to the original git command who ignores them ). Additionally
+ this command allows to checkout directories which is an extension to git-update-index.
+
``force``
If True, existing files will be overwritten even if they contain local modifications.
If False, these will trigger a CheckoutError.
``fprogress``
- see Index.add_ for signature and explanation
+ see Index.add_ for signature and explanation.
+ The provided progress information will contain None as path and item if no
+ explicit paths are given. Otherwise progress information will be send
+ prior and after a file has been checked out
``**kwargs``
Additional arguments to be pasesd to git-checkout-index
Returns
- self
+ iterable yielding paths to files which have been checked out and are
+ guaranteed to match the version stored in the index
Raise CheckoutError
If at least one file failed to be checked out. This is a summary,
@@ -1043,7 +1053,7 @@ class IndexFile(LazyMixin, diff.Diffable):
if force:
args.append("--force")
- def handle_stderr(proc):
+ def handle_stderr(proc, iter_checked_out_files):
stderr = proc.stderr.read()
if not stderr:
return
@@ -1075,9 +1085,11 @@ class IndexFile(LazyMixin, diff.Diffable):
if unknown_lines:
raise GitCommandError(("git-checkout-index", ), 128, stderr)
if failed_files:
- raise CheckoutError("Some files could not be checked out from the index due to local modifications", failed_files)
+ valid_files = list(set(iter_checked_out_files) - set(failed_files))
+ raise CheckoutError("Some files could not be checked out from the index due to local modifications", failed_files, valid_files)
# END stderr handler
+
if paths is None:
args.append("--all")
kwargs['as_process'] = 1
@@ -1085,22 +1097,51 @@ class IndexFile(LazyMixin, diff.Diffable):
proc = self.repo.git.checkout_index(*args, **kwargs)
proc.wait()
fprogress(None, True, None)
- handle_stderr(proc)
+ rval_iter = ( e.path for e in self.entries.itervalues() )
+ handle_stderr(proc, rval_iter)
+ return rval_iter
else:
if isinstance(paths, basestring):
paths = [paths]
args.append("--stdin")
- proc = self.repo.git.checkout_index(args, as_process=True, istream=subprocess.PIPE, **kwargs)
+ kwargs['as_process'] = True
+ kwargs['istream'] = subprocess.PIPE
+ proc = self.repo.git.checkout_index(args, **kwargs)
make_exc = lambda : GitCommandError(("git-checkout-index",)+args, 128, proc.stderr.read())
+ checked_out_files = list()
for path in paths:
path = self._to_relative_path(path)
- self._write_path_to_stdin(proc, path, path, make_exc, fprogress, read_from_stdout=False)
+ # if the item is not in the index, it could be a directory
+ path_is_directory = False
+ try:
+ self.entries[(path, 0)]
+ except KeyError:
+ dir = path
+ if not dir.endswith('/'):
+ dir += '/'
+ for entry in self.entries.itervalues():
+ if entry.path.startswith(dir):
+ p = entry.path
+ self._write_path_to_stdin(proc, p, p, make_exc, fprogress, read_from_stdout=False)
+ checked_out_files.append(p)
+ path_is_directory = True
+ # END if entry is in directory
+ # END for each entry
+ # END path exception handlnig
+
+ if not path_is_directory:
+ self._write_path_to_stdin(proc, path, path, make_exc, fprogress, read_from_stdout=False)
+ checked_out_files.append(path)
+ # END path is a file
# END for each path
self._flush_stdin_and_wait(proc)
- handle_stderr(proc)
+
+ handle_stderr(proc, checked_out_files)
+ return checked_out_files
+ # END directory handling
# END paths handling
- return self
+ assert "Should not reach this point"
@clear_cache
@default_index