5050def touch (filename ):
5151 fp = open (filename , "a" )
5252 fp .close ()
53+
54+
55+ def digest_process_messages (fh , progress ):
56+ """Read progress messages from file-like object fh, supplying the respective
57+ progress messages to the progress instance.
58+
59+ :return: list(line, ...) list of lines without linebreaks that did
60+ not contain progress information"""
61+ line_so_far = ''
62+ dropped_lines = list ()
63+ while True :
64+ char = fh .read (1 )
65+ if not char :
66+ break
67+
68+ if char in ('\r ' , '\n ' ):
69+ dropped_lines .extend (progress ._parse_progress_line (line_so_far ))
70+ line_so_far = ''
71+ else :
72+ line_so_far += char
73+ # END process parsed line
74+ # END while file is not done reading
75+ return dropped_lines
76+
77+ def finalize_process (proc ):
78+ """Wait for the process (fetch, pull or push) and handle its errors accordingly"""
79+ try :
80+ proc .wait ()
81+ except GitCommandError ,e :
82+ # if a push has rejected items, the command has non-zero return status
83+ # a return status of 128 indicates a connection error - reraise the previous one
84+ if proc .poll () == 128 :
85+ raise
86+ pass
87+ # END exception handling
88+
89+
90+ def get_fetch_info_from_stderr (repo , proc , progress ):
91+ # skip first line as it is some remote info we are not interested in
92+ output = IterableList ('name' )
93+
94+
95+ # lines which are no progress are fetch info lines
96+ # this also waits for the command to finish
97+ # Skip some progress lines that don't provide relevant information
98+ fetch_info_lines = list ()
99+ for line in digest_process_messages (proc .stderr , progress ):
100+ if line .startswith ('From' ) or line .startswith ('remote: Total' ):
101+ continue
102+ elif line .startswith ('warning:' ):
103+ print >> sys .stderr , line
104+ continue
105+ elif line .startswith ('fatal:' ):
106+ raise GitCommandError (("Error when fetching: %s" % line ,), 2 )
107+ # END handle special messages
108+ fetch_info_lines .append (line )
109+ # END for each line
110+
111+ # read head information
112+ fp = open (join (repo .git_dir , 'FETCH_HEAD' ),'r' )
113+ fetch_head_info = fp .readlines ()
114+ fp .close ()
115+
116+ assert len (fetch_info_lines ) == len (fetch_head_info )
117+
118+ output .extend (FetchInfo ._from_line (repo , err_line , fetch_line )
119+ for err_line ,fetch_line in zip (fetch_info_lines , fetch_head_info ))
120+
121+ finalize_process (proc )
122+ return output
123+
124+ def get_push_info (repo , proc , progress ):
125+ # read progress information from stderr
126+ # we hope stdout can hold all the data, it should ...
127+ # read the lines manually as it will use carriage returns between the messages
128+ # to override the previous one. This is why we read the bytes manually
129+ digest_process_messages (proc .stderr , progress )
130+
131+ output = IterableList ('name' )
132+ for line in proc .stdout .readlines ():
133+ try :
134+ output .append (PushInfo ._from_line (repo , line ))
135+ except ValueError :
136+ # if an error happens, additional info is given which we cannot parse
137+ pass
138+ # END exception handling
139+ # END for each line
140+
141+ finalize_process (proc )
142+ return output
53143
54144#} END utilities
55145
@@ -344,98 +434,6 @@ class CmdTransportMixin(TransportDB):
344434 have packs and the other implementations
345435 """
346436
347- @classmethod
348- def _digest_process_messages (cls , fh , progress ):
349- """Read progress messages from file-like object fh, supplying the respective
350- progress messages to the progress instance.
351-
352- :return: list(line, ...) list of lines without linebreaks that did
353- not contain progress information"""
354- line_so_far = ''
355- dropped_lines = list ()
356- while True :
357- char = fh .read (1 )
358- if not char :
359- break
360-
361- if char in ('\r ' , '\n ' ):
362- dropped_lines .extend (progress ._parse_progress_line (line_so_far ))
363- line_so_far = ''
364- else :
365- line_so_far += char
366- # END process parsed line
367- # END while file is not done reading
368- return dropped_lines
369-
370- @classmethod
371- def _finalize_proc (cls , proc ):
372- """Wait for the process (fetch, pull or push) and handle its errors accordingly"""
373- try :
374- proc .wait ()
375- except GitCommandError ,e :
376- # if a push has rejected items, the command has non-zero return status
377- # a return status of 128 indicates a connection error - reraise the previous one
378- if proc .poll () == 128 :
379- raise
380- pass
381- # END exception handling
382-
383-
384- def _get_fetch_info_from_stderr (self , proc , progress ):
385- # skip first line as it is some remote info we are not interested in
386- output = IterableList ('name' )
387-
388-
389- # lines which are no progress are fetch info lines
390- # this also waits for the command to finish
391- # Skip some progress lines that don't provide relevant information
392- fetch_info_lines = list ()
393- for line in self ._digest_process_messages (proc .stderr , progress ):
394- if line .startswith ('From' ) or line .startswith ('remote: Total' ):
395- continue
396- elif line .startswith ('warning:' ):
397- print >> sys .stderr , line
398- continue
399- elif line .startswith ('fatal:' ):
400- raise GitCommandError (("Error when fetching: %s" % line ,), 2 )
401- # END handle special messages
402- fetch_info_lines .append (line )
403- # END for each line
404-
405- # read head information
406- fp = open (join (self .git_dir , 'FETCH_HEAD' ),'r' )
407- fetch_head_info = fp .readlines ()
408- fp .close ()
409-
410- assert len (fetch_info_lines ) == len (fetch_head_info )
411-
412- output .extend (FetchInfo ._from_line (self , err_line , fetch_line )
413- for err_line ,fetch_line in zip (fetch_info_lines , fetch_head_info ))
414-
415- self ._finalize_proc (proc )
416- return output
417-
418- def _get_push_info (self , proc , progress ):
419- # read progress information from stderr
420- # we hope stdout can hold all the data, it should ...
421- # read the lines manually as it will use carriage returns between the messages
422- # to override the previous one. This is why we read the bytes manually
423- self ._digest_process_messages (proc .stderr , progress )
424-
425- output = IterableList ('name' )
426- for line in proc .stdout .readlines ():
427- try :
428- output .append (PushInfo ._from_line (self , line ))
429- except ValueError :
430- # if an error happens, additional info is given which we cannot parse
431- pass
432- # END exception handling
433- # END for each line
434-
435- self ._finalize_proc (proc )
436- return output
437-
438-
439437 #{ Transport DB interface
440438
441439 def push (self , url , refspecs = None , progress = None , ** kwargs ):
@@ -445,7 +443,7 @@ def push(self, url, refspecs=None, progress=None, **kwargs):
445443 :param progress: RemoteProgress derived instance or None
446444 :param **kwargs: Additional arguments to be passed to the git-push process"""
447445 proc = self ._git .push (url , refspecs , porcelain = True , as_process = True , ** kwargs )
448- return self . _get_push_info ( proc , progress or RemoteProgress ())
446+ return get_push_info ( self , proc , progress or RemoteProgress ())
449447
450448 def pull (self , url , refspecs = None , progress = None , ** kwargs ):
451449 """Fetch and merge the given refspecs.
@@ -455,15 +453,15 @@ def pull(self, url, refspecs=None, progress=None, **kwargs):
455453 :param refspecs: see push()
456454 :param progress: see push()"""
457455 proc = self ._git .pull (url , refspecs , with_extended_output = True , as_process = True , v = True , ** kwargs )
458- return self . _get_fetch_info_from_stderr ( proc , progress or RemoteProgress ())
456+ return get_fetch_info_from_stderr ( self , proc , progress or RemoteProgress ())
459457
460458 def fetch (self , url , refspecs = None , progress = None , ** kwargs ):
461459 """Fetch the latest changes
462460 :param url: may be a remote name or a url
463461 :param refspecs: see push()
464462 :param progress: see push()"""
465463 proc = self ._git .fetch (url , refspecs , with_extended_output = True , as_process = True , v = True , ** kwargs )
466- return self . _get_fetch_info_from_stderr ( proc , progress or RemoteProgress ())
464+ return get_fetch_info_from_stderr ( self , proc , progress or RemoteProgress ())
467465
468466 #} end transport db interface
469467
@@ -641,7 +639,7 @@ def init(cls, path=None, mkdir=True, **kwargs):
641639 return cls (path )
642640
643641 @classmethod
644- def _clone (cls , git , url , path , ** kwargs ):
642+ def _clone (cls , git , url , path , progress , ** kwargs ):
645643 # special handling for windows for path at which the clone should be
646644 # created.
647645 # tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
@@ -667,7 +665,11 @@ def _clone(cls, git, url, path, **kwargs):
667665 # END windows handling
668666
669667 try :
670- git .clone (url , path , ** kwargs )
668+ proc = git .clone (url , path , with_extended_output = True , as_process = True , v = True , ** kwargs )
669+ if progress is not None :
670+ digest_process_messages (proc .stderr , progress )
671+ #END digest progress messages
672+ finalize_process (proc )
671673 finally :
672674 if prev_cwd is not None :
673675 os .chdir (prev_cwd )
@@ -691,19 +693,20 @@ def _clone(cls, git, url, path, **kwargs):
691693 # END handle remote repo
692694 return repo
693695
694- def clone (self , path , ** kwargs ):
695- """:param kwargs:
696+ def clone (self , path , progress = None , ** kwargs ):
697+ """
698+ :param kwargs:
696699 All remaining keyword arguments are given to the git-clone command
697700
698701 For more information, see the respective method in HighLevelRepository"""
699- return self ._clone (self .git , self .git_dir , path , ** kwargs )
702+ return self ._clone (self .git , self .git_dir , path , progress or RemoteProgress (), ** kwargs )
700703
701704 @classmethod
702- def clone_from (cls , url , to_path , ** kwargs ):
705+ def clone_from (cls , url , to_path , progress = None , ** kwargs ):
703706 """
704707 :param kwargs: see the ``clone`` method
705708 For more information, see the respective method in the HighLevelRepository"""
706- return cls ._clone (cls .GitCls (os .getcwd ()), url , to_path , ** kwargs )
709+ return cls ._clone (cls .GitCls (os .getcwd ()), url , to_path , progress or RemoteProgress (), ** kwargs )
707710
708711 def archive (self , ostream , treeish = None , prefix = None , ** kwargs ):
709712 """For all args see HighLevelRepository interface
0 commit comments