Skip to content

Commit fef3a7c

Browse files
dschogitster
authored andcommitted
cvsexportcommit: be graceful when "cvs status" reorders the arguments
In my use cases, "cvs status" sometimes reordered the passed filenames, which often led to a misdetection of a dirty state (when it was in reality a clean state). I finally tracked it down to two filenames having the same basename. So no longer trust the order of the results blindly, but actually check the file name. Since "cvs status" only returns the basename (and the complete path on the server which is useless for our purposes), run "cvs status" several times with lists consisting of files with unique (chomped) basenames. Be a bit clever about new files: these are reported as "no file <blabla>", so in order to discern it from existing files, prepend "no file " to the basename. In other words, one call to "cvs status" will not ask for two files "blabla" (which does not yet exist) and "no file blabla" (which exists). This patch makes cvsexportcommit slightly slower, when the list of changed files has non-unique basenames, but at least it is accurate now. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent e5fc9a0 commit fef3a7c

File tree

2 files changed

+67
-8
lines changed

2 files changed

+67
-8
lines changed

git-cvsexportcommit.perl

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,39 @@
198198
my @updated = xargs_safe_pipe_capture([@cvs, 'update'], @canstatusfiles);
199199
print @updated;
200200
}
201-
my @cvsoutput;
202-
@cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles);
203-
my $matchcount = 0;
204-
foreach my $l (@cvsoutput) {
205-
chomp $l;
206-
if ( $l =~ /^File:/ and $l =~ /Status: (.*)$/ ) {
207-
$cvsstat{$canstatusfiles[$matchcount]} = $1;
208-
$matchcount++;
201+
# "cvs status" reorders the parameters, notably when there are multiple
202+
# arguments with the same basename. So be precise here.
203+
204+
my %added = map { $_ => 1 } @afiles;
205+
my %todo = map { $_ => 1 } @canstatusfiles;
206+
207+
while (%todo) {
208+
my @canstatusfiles2 = ();
209+
my %fullname = ();
210+
foreach my $name (keys %todo) {
211+
my $basename = basename($name);
212+
213+
$basename = "no file " . $basename if (exists($added{$basename}));
214+
chomp($basename);
215+
216+
if (!exists($fullname{$basename})) {
217+
$fullname{$basename} = $name;
218+
push (@canstatusfiles2, $name);
219+
delete($todo{$name});
209220
}
221+
}
222+
my @cvsoutput;
223+
@cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles2);
224+
foreach my $l (@cvsoutput) {
225+
chomp $l;
226+
if ($l =~ /^File:\s+(.*\S)\s+Status: (.*)$/) {
227+
if (!exists($fullname{$1})) {
228+
print STDERR "Huh? Status reported for unexpected file '$1'\n";
229+
} else {
230+
$cvsstat{$fullname{$1}} = $2;
231+
}
232+
}
233+
}
210234
}
211235
}
212236

t/t9200-git-cvsexportcommit.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,4 +246,39 @@ test_expect_success \
246246
;;
247247
esac
248248

249+
test_expect_success 'check files before directories' '
250+
251+
echo Notes > release-notes &&
252+
git add release-notes &&
253+
git commit -m "Add release notes" release-notes &&
254+
id=$(git rev-parse HEAD) &&
255+
git cvsexportcommit -w "$CVSWORK" -c $id &&
256+
257+
echo new > DS &&
258+
echo new > E/DS &&
259+
echo modified > release-notes &&
260+
git add DS E/DS release-notes &&
261+
git commit -m "Add two files with the same basename" &&
262+
id=$(git rev-parse HEAD) &&
263+
git cvsexportcommit -w "$CVSWORK" -c $id &&
264+
check_entries "$CVSWORK/E" "DS/1.1/|newfile5.txt/1.1/" &&
265+
check_entries "$CVSWORK" "DS/1.1/|release-notes/1.2/" &&
266+
diff -u "$CVSWORK/DS" DS &&
267+
diff -u "$CVSWORK/E/DS" E/DS &&
268+
diff -u "$CVSWORK/release-notes" release-notes
269+
270+
'
271+
272+
test_expect_success 'commit a file with leading spaces in the name' '
273+
274+
echo space > " space" &&
275+
git add " space" &&
276+
git commit -m "Add a file with a leading space" &&
277+
id=$(git rev-parse HEAD) &&
278+
git cvsexportcommit -w "$CVSWORK" -c $id &&
279+
check_entries "$CVSWORK" " space/1.1/|DS/1.1/|release-notes/1.2/" &&
280+
diff -u "$CVSWORK/ space" " space"
281+
282+
'
283+
249284
test_done

0 commit comments

Comments
 (0)