2727# resolve target commit
2828my $commit ;
2929$commit = pop @ARGV ;
30- $commit = ` git-rev-parse --verify "$commit "^0 ` ;
30+ $commit = safe_pipe_capture( ' git-rev-parse' , ' --verify' , " $commit ^0 " ) ;
3131chomp $commit ;
3232if ($? ) {
3333 die " The commit reference $commit did not resolve!" ;
3737my $parent ;
3838if (@ARGV ) {
3939 $parent = pop @ARGV ;
40- $parent = ` git-rev-parse --verify "$parent " ^0"` ;
40+ $parent = safe_pipe_capture( ' git-rev-parse' , ' --verify' , " $parent ^0" ) ;
4141 chomp $parent ;
4242 if ($? ) {
4343 die " The parent reference did not resolve!" ;
4444 }
4545}
4646
4747# find parents from the commit itself
48- my @commit = ` git-cat-file commit $commit ` ;
48+ my @commit = safe_pipe_capture( ' git-cat-file' , ' commit' , $commit ) ;
4949my @parents ;
5050foreach my $p (@commit ) {
5151 if ($p =~ m / ^$ / ) { # end of commit headers, we're done
8181$? && die " Error extracting the commit message" ;
8282
8383my (@afiles , @dfiles , @mfiles );
84- my @files = ` git-diff-tree -r $parent $commit ` ;
84+ my @files = safe_pipe_capture( ' git-diff-tree' , ' -r ' , $parent , $commit ) ;
8585print @files ;
8686$? && die " Error in git-diff-tree" ;
8787foreach my $f (@files ) {
8888 chomp $f ;
89- my @fields = split (m / \s +/ , $f );
89+ my @fields = split (m ! \s +! , $f );
9090 if ($fields [4] eq ' A' ) {
9191 push @afiles , $fields [5];
9292 }
104104# check that the files are clean and up to date according to cvs
105105my $dirty ;
106106foreach my $f (@afiles ) {
107- my $status = ` cvs -q status "$f " | grep '^File: '` ;
108-
109- unless ($status =~ m / Status: Unknown$ / ) {
110- $dirty = 1;
107+ # This should return only one value
108+ my @status = grep (m / ^File/ , safe_pipe_capture(' cvs' , ' -q' , ' status' ,$f ));
109+ if (@status > 1) { warn ' Strange! cvs status returned more than one line?' };
110+ unless ($status [0] =~ m / Status: Unknown$ / ) {
111+ $dirty = 1;
111112 warn " File $f is already known in your CVS checkout!\n " ;
112113 }
113114}
114115foreach my $f (@mfiles , @dfiles ) {
115116 # TODO:we need to handle removed in cvs
116- my $ status = ` cvs -q status " $f " | grep '^File: ' ` ;
117-
118- unless ($status =~ m / Status: Up-to-date$ / ) {
117+ my @ status = grep ( m / ^File / , safe_pipe_capture( ' cvs' , ' -q ' , ' status' , $f )) ;
118+ if ( @status > 1) { warn ' Strange! cvs status returned more than one line? ' };
119+ unless ($status [0] =~ m / Status: Up-to-date$ / ) {
119120 $dirty = 1;
120121 warn " File $f not up to date in your CVS checkout!\n " ;
121122 }
132133
133134print " 'Patching' binary files\n " ;
134135
135- my @bfiles = ` git-diff-tree -p $parent $commit | grep '^Binary' ` ;
136+ my @bfiles = grep ( m / ^Binary / , safe_pipe_capture( ' git-diff-tree' , ' -p ' , $parent , $commit )) ;
136137@bfiles = map { chomp } @bfiles ;
137138foreach my $f (@bfiles ) {
138139 # check that the file in cvs matches the "old" file
139140 # extract the file to $tmpdir and comparre with cmp
140- my $tree = ` git-rev-parse $parent ^{tree} ` ;
141+ my $tree = safe_pipe_capture( ' git-rev-parse' , " $parent ^{tree}" ) ;
141142 chomp $tree ;
142143 my $blob = ` git-ls-tree $tree "$f " | cut -f 1 | cut -d ' ' -f 3` ;
143144 chomp $blob ;
144145 ` git-cat-file blob $blob > $tmpdir /blob` ;
145- ` cmp -q $f $tmpdir /blob` ;
146- if ($? ) {
146+ if (system (' cmp' , ' -q' , $f , " $tmpdir /blob" )) {
147147 warn " Binary file $f in CVS does not match parent.\n " ;
148148 $dirty = 1;
149149 next ;
175175}
176176
177177foreach my $f (@afiles ) {
178- ` cvs add $f ` ;
178+ system ( ' cvs' , ' add' , $f ) ;
179179 if ($? ) {
180180 $dirty = 1;
181181 warn " Failed to cvs add $f -- you may need to do it manually" ;
182182 }
183183}
184184
185185foreach my $f (@dfiles ) {
186- ` cvs rm -f $f ` ;
186+ system ( ' cvs' , ' rm ' , ' -f ' , $f ) ;
187187 if ($? ) {
188188 $dirty = 1;
189189 warn " Failed to cvs rm -f $f -- you may need to do it manually" ;
204204
205205if ($opt_c ) {
206206 print " Autocommit\n $cmd \n " ;
207- print ` cvs commit -F .msg $commitfiles 2>&1 ` ;
207+ print safe_pipe_capture( ' cvs' , ' commit' , ' -F ' , ' .msg' , @afiles , @mfiles , @dfiles ) ;
208208 if ($? ) {
209209 cleanupcvs(@files );
210210 die " Exiting: The commit did not succeed" ;
@@ -224,10 +224,23 @@ END
224224sub cleanupcvs {
225225 my @files = @_ ;
226226 foreach my $f (@files ) {
227- ` cvs -q update -C " $f " ` ;
227+ system ( ' cvs' , ' -q ' , ' update' , ' -C ' , $f ) ;
228228 if ($? ) {
229229 warn " Warning! Failed to cleanup state of $f \n " ;
230230 }
231231 }
232232}
233233
234+ # An alterative to `command` that allows input to be passed as an array
235+ # to work around shell problems with weird characters in arguments
236+ # if the exec returns non-zero we die
237+ sub safe_pipe_capture {
238+ my @output ;
239+ if (my $pid = open my $child , ' -|' ) {
240+ @output = (<$child >);
241+ close $child or die join (' ' ,@_ )." : $! $? " ;
242+ } else {
243+ exec (@_ ) or die " $! $? " ; # exec() can fail the executable can't be found
244+ }
245+ return wantarray ? @output : join (' ' ,@output );
246+ }
0 commit comments