Skip to content

Commit d41df15

Browse files
Martin LanghoffJunio C Hamano
authored andcommitted
exportcommit: replace backticks with safe_pipe_capture() or system() - initial pass
Replaced backticks with potentially troublesome unescaped input with safe_pipe_capture(). Signed-off-by: Martin Langhoff <martin@catalyst.net.nz> Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 5179c8a commit d41df15

File tree

1 file changed

+33
-20
lines changed

1 file changed

+33
-20
lines changed

git-cvsexportcommit.perl

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
# resolve target commit
2828
my $commit;
2929
$commit = pop @ARGV;
30-
$commit = `git-rev-parse --verify "$commit"^0`;
30+
$commit = safe_pipe_capture('git-rev-parse', '--verify', "$commit^0");
3131
chomp $commit;
3232
if ($?) {
3333
die "The commit reference $commit did not resolve!";
@@ -37,15 +37,15 @@
3737
my $parent;
3838
if (@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);
4949
my @parents;
5050
foreach my $p (@commit) {
5151
if ($p =~ m/^$/) { # end of commit headers, we're done
@@ -81,12 +81,12 @@
8181
$? && die "Error extracting the commit message";
8282

8383
my (@afiles, @dfiles, @mfiles);
84-
my @files = `git-diff-tree -r $parent $commit`;
84+
my @files = safe_pipe_capture('git-diff-tree', '-r', $parent, $commit);
8585
print @files;
8686
$? && die "Error in git-diff-tree";
8787
foreach 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
}
@@ -104,18 +104,19 @@
104104
# check that the files are clean and up to date according to cvs
105105
my $dirty;
106106
foreach 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
}
114115
foreach 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
}
@@ -132,18 +133,17 @@
132133

133134
print "'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;
137138
foreach 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;
@@ -175,15 +175,15 @@
175175
}
176176

177177
foreach 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

185185
foreach 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";
@@ -204,7 +204,7 @@
204204

205205
if ($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
224224
sub 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

Comments
 (0)