Skip to content

Commit 30e215a

Browse files
ericrannaudgitster
authored andcommitted
fast-import: checkpoint: dump branches/tags/marks even if object_count==0
The checkpoint command cycles packfiles if object_count != 0, a sensible test or there would be no pack files to write. Since 820b931, the command also dumps branches, tags and marks, but still conditionally. However, it is possible for a command stream to modify refs or create marks without creating any new objects. For example, reset a branch (and keep fast-import running): $ git fast-import reset refs/heads/master from refs/heads/master^ checkpoint but refs/heads/master remains unchanged. Other example: a commit command that re-creates an object that already exists in the object database. The man page also states that checkpoint "updates the refs" and that "placing a progress command immediately after a checkpoint will inform the reader when the checkpoint has been completed and it can safely access the refs that fast-import updated". This wasn't always true without this patch. This fix unconditionally calls dump_{branches,tags,marks}() for all checkpoint commands. dump_branches() and dump_tags() are cheap to call in the case of a no-op. Add tests to t9300 that observe the (non-packfiles) effects of checkpoint. Signed-off-by: Eric Rannaud <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 94c9fd2 commit 30e215a

File tree

2 files changed

+145
-3
lines changed

2 files changed

+145
-3
lines changed

fast-import.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3188,10 +3188,10 @@ static void checkpoint(void)
31883188
checkpoint_requested = 0;
31893189
if (object_count) {
31903190
cycle_packfile();
3191-
dump_branches();
3192-
dump_tags();
3193-
dump_marks();
31943191
}
3192+
dump_branches();
3193+
dump_tags();
3194+
dump_marks();
31953195
}
31963196

31973197
static void parse_checkpoint(void)

t/t9300-fast-import.sh

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3120,4 +3120,146 @@ test_expect_success 'U: validate root delete result' '
31203120
compare_diff_raw expect actual
31213121
'
31223122

3123+
###
3124+
### series V (checkpoint)
3125+
###
3126+
3127+
# The commands in input_file should not produce any output on the file
3128+
# descriptor set with --cat-blob-fd (or stdout if unspecified).
3129+
#
3130+
# To make sure you're observing the side effects of checkpoint *before*
3131+
# fast-import terminates (and thus writes out its state), check that the
3132+
# fast-import process is still running using background_import_still_running
3133+
# *after* evaluating the test conditions.
3134+
background_import_then_checkpoint () {
3135+
options=$1
3136+
input_file=$2
3137+
3138+
mkfifo V.input
3139+
exec 8<>V.input
3140+
rm V.input
3141+
3142+
mkfifo V.output
3143+
exec 9<>V.output
3144+
rm V.output
3145+
3146+
git fast-import $options <&8 >&9 &
3147+
echo $! >V.pid
3148+
# We don't mind if fast-import has already died by the time the test
3149+
# ends.
3150+
test_when_finished "exec 8>&-; exec 9>&-; kill $(cat V.pid) || true"
3151+
3152+
# Start in the background to ensure we adhere strictly to (blocking)
3153+
# pipes writing sequence. We want to assume that the write below could
3154+
# block, e.g. if fast-import blocks writing its own output to &9
3155+
# because there is no reader on &9 yet.
3156+
(
3157+
cat "$input_file"
3158+
echo "checkpoint"
3159+
echo "progress checkpoint"
3160+
) >&8 &
3161+
3162+
error=1 ;# assume the worst
3163+
while read output <&9
3164+
do
3165+
if test "$output" = "progress checkpoint"
3166+
then
3167+
error=0
3168+
break
3169+
fi
3170+
# otherwise ignore cruft
3171+
echo >&2 "cruft: $output"
3172+
done
3173+
3174+
if test $error -eq 1
3175+
then
3176+
false
3177+
fi
3178+
}
3179+
3180+
background_import_still_running () {
3181+
if ! kill -0 "$(cat V.pid)"
3182+
then
3183+
echo >&2 "background fast-import terminated too early"
3184+
false
3185+
fi
3186+
}
3187+
3188+
test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
3189+
cat >input <<-INPUT_END &&
3190+
progress foo
3191+
progress bar
3192+
3193+
INPUT_END
3194+
3195+
background_import_then_checkpoint "" input &&
3196+
background_import_still_running
3197+
'
3198+
3199+
test_expect_success PIPE 'V: checkpoint updates refs after reset' '
3200+
cat >input <<-\INPUT_END &&
3201+
reset refs/heads/V
3202+
from refs/heads/U
3203+
3204+
INPUT_END
3205+
3206+
background_import_then_checkpoint "" input &&
3207+
test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
3208+
background_import_still_running
3209+
'
3210+
3211+
test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
3212+
cat >input <<-INPUT_END &&
3213+
commit refs/heads/V
3214+
mark :1
3215+
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3216+
data 0
3217+
from refs/heads/U
3218+
3219+
INPUT_END
3220+
3221+
background_import_then_checkpoint "--export-marks=marks.actual" input &&
3222+
3223+
echo ":1 $(git rev-parse --verify V)" >marks.expected &&
3224+
3225+
test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
3226+
test_cmp marks.expected marks.actual &&
3227+
background_import_still_running
3228+
'
3229+
3230+
# Re-create the exact same commit, but on a different branch: no new object is
3231+
# created in the database, but the refs and marks still need to be updated.
3232+
test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
3233+
cat >input <<-INPUT_END &&
3234+
commit refs/heads/V2
3235+
mark :2
3236+
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3237+
data 0
3238+
from refs/heads/U
3239+
3240+
INPUT_END
3241+
3242+
background_import_then_checkpoint "--export-marks=marks.actual" input &&
3243+
3244+
echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
3245+
3246+
test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
3247+
test_cmp marks.expected marks.actual &&
3248+
background_import_still_running
3249+
'
3250+
3251+
test_expect_success PIPE 'V: checkpoint updates tags after tag' '
3252+
cat >input <<-INPUT_END &&
3253+
tag Vtag
3254+
from refs/heads/V
3255+
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
3256+
data 0
3257+
3258+
INPUT_END
3259+
3260+
background_import_then_checkpoint "" input &&
3261+
git show-ref -d Vtag &&
3262+
background_import_still_running
3263+
'
3264+
31233265
test_done

0 commit comments

Comments
 (0)