diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2009-11-23 11:14:28 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2009-11-23 11:34:38 +0100 |
commit | 3bee808e15707d849c00e8cea8106e41dd96d771 (patch) | |
tree | 7f255aa6524409a9b566ad78318b1f4f89334aae /lib/git/index.py | |
parent | 331ddc27a22bde33542f8c1a00b6b56da32e5033 (diff) | |
download | gitpython-3bee808e15707d849c00e8cea8106e41dd96d771.tar.gz |
index.checkout: Now parsing stderror in the end to determine which files have not been updated as they where modified locally or did not exist. Test was improved to check for this new case.
Diffstat (limited to 'lib/git/index.py')
-rw-r--r-- | lib/git/index.py | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/lib/git/index.py b/lib/git/index.py index 6485ff11..fa6bf185 100644 --- a/lib/git/index.py +++ b/lib/git/index.py @@ -24,6 +24,20 @@ from git.objects import Blob, Tree, Object, Commit from git.utils import SHA1Writer, LazyMixin, ConcurrentWriteOperation, join_path_native +class CheckoutError( Exception ): + """Thrown if a file could not be checked out from the index as it contained + 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) + self.failed_files = failed_files + + def __str__(self): + return super(CheckoutError, self).__str__() + ":%s" % self.failed_files + + class _TemporaryFileSwap(object): """ Utility class moving a file to a temporary location within the same directory @@ -800,7 +814,7 @@ class IndexFile(LazyMixin, diff.Diffable): # to get suitable progress information, pipe paths to stdin args = ("--add", "--replace", "--verbose", "--stdin") proc = self.repo.git.update_index(*args, **{'as_process':True, 'istream':subprocess.PIPE}) - make_exc = lambda : GitCommandError(("git-update-index",)+args, 128, proc.stderr.readline()) + make_exc = lambda : GitCommandError(("git-update-index",)+args, 128, proc.stderr.read()) added_files = list() for filepath in self._iter_expand_paths(paths): @@ -829,7 +843,7 @@ class IndexFile(LazyMixin, diff.Diffable): # send progress for these now. args = ("-w", "--stdin-paths") proc = self.repo.git.hash_object(*args, **{'istream':subprocess.PIPE, 'as_process':True}) - make_exc = lambda : GitCommandError(("git-hash-object",)+args, 128, proc.stderr.readline()) + make_exc = lambda : GitCommandError(("git-hash-object",)+args, 128, proc.stderr.read()) obj_ids = list() for ei in null_entries_indices: entry = entries[ei] @@ -999,13 +1013,16 @@ class IndexFile(LazyMixin, diff.Diffable): ``paths`` If None, all paths in the index will be checked out. Otherwise an iterable - or single path of relative or absolute paths pointing to files is expected. - The command will ignore paths that do not exist. - The provided progress information will contain None as path and item. + 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. ``force`` - If True, existing files will be overwritten. If False, these will - be skipped. + 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 @@ -1015,28 +1032,66 @@ class IndexFile(LazyMixin, diff.Diffable): Returns self + + Raise CheckoutError + If at least one file failed to be checked out. This is a summary, + hence it will checkout as many files as it can anyway. + Raise GitCommandError if error lines could not be parsed - this truly is + an exceptional state """ args = ["--index"] if force: args.append("--force") + def handle_stderr(proc): + stderr = proc.stderr.read() + if not stderr: + return + # line contents: + # git-checkout-index: this already exists + failed_files = list() + unknown_lines = list() + endings = (' already exists', ' is not in the cache', ' does not exist at stage', ' is unmerged') + for line in stderr.splitlines(): + if not line.startswith("git checkout-index: ") and not line.startswith("git-checkout-index: "): + unknown_lines.append(line) + continue + # END unkown lines parsing + + for e in endings: + if line.endswith(e): + failed_files.append(line[20:-len(e)]) + break + # END if ending matches + # END for each possible ending + # END for each line + 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) + # END stderr handler + if paths is None: args.append("--all") + kwargs['as_process'] = 1 fprogress(None, False, None) - self.repo.git.checkout_index(*args, **kwargs) + proc = self.repo.git.checkout_index(*args, **kwargs) + proc.wait() fprogress(None, True, None) + handle_stderr(proc) else: - if not isinstance(paths, (tuple,list)): + if isinstance(paths, basestring): paths = [paths] args.append("--stdin") - co_proc = self.repo.git.checkout_index(args, as_process=True, istream=subprocess.PIPE, **kwargs) - make_exc = lambda : GitCommandError(("git-checkout-index",)+args, 128, co_proc.stderr.readline()) + proc = self.repo.git.checkout_index(args, as_process=True, istream=subprocess.PIPE, **kwargs) + make_exc = lambda : GitCommandError(("git-checkout-index",)+args, 128, proc.stderr.read()) for path in paths: path = self._to_relative_path(path) - self._write_path_to_stdin(co_proc, path, path, make_exc, fprogress, read_from_stdout=False) - # END for each path - self._flush_stdin_and_wait(co_proc) + self._write_path_to_stdin(proc, path, path, make_exc, fprogress, read_from_stdout=False) + # END for each path + self._flush_stdin_and_wait(proc) + handle_stderr(proc) # END paths handling return self |