@@ -29,13 +29,18 @@ class CheckoutError( Exception ):
2929 changes.
3030
3131 The .failed_files attribute contains a list of relative paths that failed
32- to be checked out as they contained changes that did not exist in the index"""
33- def __init__ (self , message , failed_files ):
34- super (CheckoutError , self ).__init__ (message )
32+ to be checked out as they contained changes that did not exist in the index.
33+
34+ The .valid_files attribute contains a list of relative paths to files that
35+ were checked out successfully and hence match the version stored in the
36+ index"""
37+ def __init__ (self , message , failed_files , valid_files ):
38+ Exception .__init__ (self , message )
3539 self .failed_files = failed_files
40+ self .valid_files = valid_files
3641
3742 def __str__ (self ):
38- return super ( CheckoutError , self ) .__str__ () + ":%s" % self .failed_files
43+ return Exception .__str__ (self ) + ":%s" % self .failed_files
3944
4045
4146class _TemporaryFileSwap (object ):
@@ -1009,29 +1014,34 @@ def _flush_stdin_and_wait(cls, proc):
10091014 @default_index
10101015 def checkout (self , paths = None , force = False , fprogress = lambda * args : None , ** kwargs ):
10111016 """
1012- Checkout the given paths or all files from the version in the index.
1017+ Checkout the given paths or all files from the version known to the index into
1018+ the working tree.
10131019
10141020 ``paths``
10151021 If None, all paths in the index will be checked out. Otherwise an iterable
1016- of relative or absolute paths or a single path pointing to files in the index
1017- is expected.
1018- The command will raise of files do not exist in the index ( as opposed to the
1019- original git command who ignores them )
1020- The provided progress information will contain None as path and item if no
1021- explicit paths are given.
1022+ of relative or absolute paths or a single path pointing to files or directories
1023+ in the index is expected.
1024+ The command will raise of files or directories do not exist in the index
1025+ ( as opposed to the original git command who ignores them ). Additionally
1026+ this command allows to checkout directories which is an extension to git-update-index.
1027+
10221028
10231029 ``force``
10241030 If True, existing files will be overwritten even if they contain local modifications.
10251031 If False, these will trigger a CheckoutError.
10261032
10271033 ``fprogress``
1028- see Index.add_ for signature and explanation
1034+ see Index.add_ for signature and explanation.
1035+ The provided progress information will contain None as path and item if no
1036+ explicit paths are given. Otherwise progress information will be send
1037+ prior and after a file has been checked out
10291038
10301039 ``**kwargs``
10311040 Additional arguments to be pasesd to git-checkout-index
10321041
10331042 Returns
1034- self
1043+ iterable yielding paths to files which have been checked out and are
1044+ guaranteed to match the version stored in the index
10351045
10361046 Raise CheckoutError
10371047 If at least one file failed to be checked out. This is a summary,
@@ -1043,7 +1053,7 @@ def checkout(self, paths=None, force=False, fprogress=lambda *args: None, **kwar
10431053 if force :
10441054 args .append ("--force" )
10451055
1046- def handle_stderr (proc ):
1056+ def handle_stderr (proc , iter_checked_out_files ):
10471057 stderr = proc .stderr .read ()
10481058 if not stderr :
10491059 return
@@ -1075,32 +1085,63 @@ def handle_stderr(proc):
10751085 if unknown_lines :
10761086 raise GitCommandError (("git-checkout-index" , ), 128 , stderr )
10771087 if failed_files :
1078- raise CheckoutError ("Some files could not be checked out from the index due to local modifications" , failed_files )
1088+ valid_files = list (set (iter_checked_out_files ) - set (failed_files ))
1089+ raise CheckoutError ("Some files could not be checked out from the index due to local modifications" , failed_files , valid_files )
10791090 # END stderr handler
10801091
1092+
10811093 if paths is None :
10821094 args .append ("--all" )
10831095 kwargs ['as_process' ] = 1
10841096 fprogress (None , False , None )
10851097 proc = self .repo .git .checkout_index (* args , ** kwargs )
10861098 proc .wait ()
10871099 fprogress (None , True , None )
1088- handle_stderr (proc )
1100+ rval_iter = ( e .path for e in self .entries .itervalues () )
1101+ handle_stderr (proc , rval_iter )
1102+ return rval_iter
10891103 else :
10901104 if isinstance (paths , basestring ):
10911105 paths = [paths ]
10921106
10931107 args .append ("--stdin" )
1094- proc = self .repo .git .checkout_index (args , as_process = True , istream = subprocess .PIPE , ** kwargs )
1108+ kwargs ['as_process' ] = True
1109+ kwargs ['istream' ] = subprocess .PIPE
1110+ proc = self .repo .git .checkout_index (args , ** kwargs )
10951111 make_exc = lambda : GitCommandError (("git-checkout-index" ,)+ args , 128 , proc .stderr .read ())
1112+ checked_out_files = list ()
10961113 for path in paths :
10971114 path = self ._to_relative_path (path )
1098- self ._write_path_to_stdin (proc , path , path , make_exc , fprogress , read_from_stdout = False )
1115+ # if the item is not in the index, it could be a directory
1116+ path_is_directory = False
1117+ try :
1118+ self .entries [(path , 0 )]
1119+ except KeyError :
1120+ dir = path
1121+ if not dir .endswith ('/' ):
1122+ dir += '/'
1123+ for entry in self .entries .itervalues ():
1124+ if entry .path .startswith (dir ):
1125+ p = entry .path
1126+ self ._write_path_to_stdin (proc , p , p , make_exc , fprogress , read_from_stdout = False )
1127+ checked_out_files .append (p )
1128+ path_is_directory = True
1129+ # END if entry is in directory
1130+ # END for each entry
1131+ # END path exception handlnig
1132+
1133+ if not path_is_directory :
1134+ self ._write_path_to_stdin (proc , path , path , make_exc , fprogress , read_from_stdout = False )
1135+ checked_out_files .append (path )
1136+ # END path is a file
10991137 # END for each path
11001138 self ._flush_stdin_and_wait (proc )
1101- handle_stderr (proc )
1139+
1140+ handle_stderr (proc , checked_out_files )
1141+ return checked_out_files
1142+ # END directory handling
11021143 # END paths handling
1103- return self
1144+ assert "Should not reach this point"
11041145
11051146 @clear_cache
11061147 @default_index
0 commit comments