builtin/checkout: compute checkout metadata for checkouts
Provide commit metadata for checkout code paths that use unpack_trees and friends. When we're checking out a commit, use the commit information, but don't provide commit information if we're checking out from the index, since there need not be any particular commit associated with the index, and even if there is one, we can't know what it is. Signed-off-by: brian m. carlson <bk2204@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
brian m. carlson committed
Mar 16, 2020 at 18:05 UTC
13e7ed6a3a0ecd5d50b7bba2d86ce9d88494fa9b
6 files changed
+68
-33
builtin/checkout.c
+14
-4
@@ -604,7 +604,8 @@ static void describe_detached_head(const char *msg, struct commit *commit)
604
}
605
606
static int reset_tree(struct tree *tree, const struct checkout_opts *o,
607
- int worktree, int *writeout_error)
607
+ int worktree, int *writeout_error,
608
+ struct branch_info *info)
609
{
610
struct unpack_trees_options opts;
611
struct tree_desc tree_desc;
@@ -619,6 +620,11 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
620
opts.verbose_update = o->show_progress;
621
opts.src_index = &the_index;
622
opts.dst_index = &the_index;
623
+ init_checkout_metadata(&opts.meta, info->refname,
624
+ info->commit ? &info->commit->object.oid :
625
+ is_null_oid(&info->oid) ? &tree->object.oid :
626
+ &info->oid,
627
+ NULL);
628
parse_tree(tree);
629
init_tree_desc(&tree_desc, tree->buffer, tree->size);
630
switch (unpack_trees(1, &tree_desc, &opts)) {
@@ -677,7 +683,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
683
} else
684
new_tree = get_commit_tree(new_branch_info->commit);
685
if (opts->discard_changes) {
680
- ret = reset_tree(new_tree, opts, 1, writeout_error);
686
+ ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info);
687
if (ret)
688
return ret;
689
} else {
@@ -706,6 +712,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
712
topts.quiet = opts->merge && old_branch_info->commit;
713
topts.verbose_update = opts->show_progress;
714
topts.fn = twoway_merge;
715
+ init_checkout_metadata(&topts.meta, new_branch_info->refname,
716
+ new_branch_info->commit ?
717
+ &new_branch_info->commit->object.oid :
718
+ &new_branch_info->oid, NULL);
719
if (opts->overwrite_ignore) {
720
topts.dir = xcalloc(1, sizeof(*topts.dir));
721
topts.dir->flags |= DIR_SHOW_IGNORED;
@@ -776,7 +786,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
786
787
ret = reset_tree(new_tree,
788
opts, 1,
779
- writeout_error);
789
+ writeout_error, new_branch_info);
790
if (ret)
791
return ret;
792
o.ancestor = old_branch_info->name;
@@ -796,7 +806,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
806
exit(128);
807
ret = reset_tree(new_tree,
808
opts, 0,
799
- writeout_error);
809
+ writeout_error, new_branch_info);
810
strbuf_release(&o.obuf);
811
strbuf_release(&old_commit_shortname);
812
if (ret)
merge.c
+1
@@ -94,6 +94,7 @@ int checkout_fast_forward(struct repository *r,
94
opts.verbose_update = 1;
95
opts.merge = 1;
96
opts.fn = twoway_merge;
97
+ init_checkout_metadata(&opts.meta, NULL, remote, NULL);
98
setup_unpack_trees_porcelain(&opts, "merge");
99
100
if (unpack_trees(nr_trees, t, &opts)) {
t/t0021-conversion.sh
+50
-28
@@ -364,6 +364,10 @@ test_expect_success PERL 'required process filter should filter data' '
364
S=$(file_size test.r) &&
365
S2=$(file_size test2.r) &&
366
S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
367
+ M=$(git hash-object test.r) &&
368
+ M2=$(git hash-object test2.r) &&
369
+ M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") &&
370
+ EMPTY=$(git hash-object /dev/null) &&
371
372
filter_git add . &&
373
cat >expected.log <<-EOF &&
@@ -378,14 +382,15 @@ test_expect_success PERL 'required process filter should filter data' '
382
test_cmp_count expected.log debug.log &&
383
384
git commit -m "test commit 2" &&
385
+ META="ref=refs/heads/master treeish=$(git rev-parse --verify master)" &&
386
rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x=.r" &&
387
388
filter_git checkout --quiet --no-progress . &&
389
cat >expected.log <<-EOF &&
390
START
391
init handshake complete
387
- IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
388
- IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK]
392
+ IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
393
+ IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
394
STOP
395
EOF
396
test_cmp_exclude_clean expected.log debug.log &&
@@ -406,10 +411,10 @@ test_expect_success PERL 'required process filter should filter data' '
411
cat >expected.log <<-EOF &&
412
START
413
init handshake complete
409
- IN: smudge test.r $S [OK] -- OUT: $S . [OK]
410
- IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
411
- IN: smudge test4-empty.r 0 [OK] -- OUT: 0 [OK]
412
- IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK]
414
+ IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
415
+ IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
416
+ IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
417
+ IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
418
STOP
419
EOF
420
test_cmp_exclude_clean expected.log debug.log &&
@@ -519,17 +524,22 @@ test_expect_success PERL 'required process filter should process multiple packet
524
EOF
525
test_cmp_count expected.log debug.log &&
526
522
- rm -f *.file &&
527
+ M1="blob=$(git hash-object 1pkt_1__.file)" &&
528
+ M2="blob=$(git hash-object 2pkt_1+1.file)" &&
529
+ M3="blob=$(git hash-object 2pkt_2-1.file)" &&
530
+ M4="blob=$(git hash-object 2pkt_2__.file)" &&
531
+ M5="blob=$(git hash-object 3pkt_2+1.file)" &&
532
+ rm -f *.file debug.log &&
533
534
filter_git checkout --quiet --no-progress -- *.file &&
535
cat >expected.log <<-EOF &&
536
START
537
init handshake complete
528
- IN: smudge 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK]
529
- IN: smudge 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
530
- IN: smudge 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
531
- IN: smudge 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
532
- IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
538
+ IN: smudge 1pkt_1__.file $M1 $(($S )) [OK] -- OUT: $(($S )) . [OK]
539
+ IN: smudge 2pkt_1+1.file $M2 $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
540
+ IN: smudge 2pkt_2-1.file $M3 $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
541
+ IN: smudge 2pkt_2__.file $M4 $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
542
+ IN: smudge 3pkt_2+1.file $M5 $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
543
STOP
544
EOF
545
test_cmp_exclude_clean expected.log debug.log &&
@@ -578,6 +588,10 @@ test_expect_success PERL 'process filter should restart after unexpected write f
588
S=$(file_size test.r) &&
589
S2=$(file_size test2.r) &&
590
SF=$(file_size smudge-write-fail.r) &&
591
+ M=$(git hash-object test.r) &&
592
+ M2=$(git hash-object test2.r) &&
593
+ MF=$(git hash-object smudge-write-fail.r) &&
594
+ rm -f debug.log &&
595
596
git add . &&
597
rm -f *.r &&
@@ -591,11 +605,11 @@ test_expect_success PERL 'process filter should restart after unexpected write f
605
cat >expected.log <<-EOF &&
606
START
607
init handshake complete
594
- IN: smudge smudge-write-fail.r $SF [OK] -- [WRITE FAIL]
608
+ IN: smudge smudge-write-fail.r blob=$MF $SF [OK] -- [WRITE FAIL]
609
START
610
init handshake complete
597
- IN: smudge test.r $S [OK] -- OUT: $S . [OK]
598
- IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
611
+ IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK]
612
+ IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
613
STOP
614
EOF
615
test_cmp_exclude_clean expected.log debug.log &&
@@ -629,6 +643,10 @@ test_expect_success PERL 'process filter should not be restarted if it signals a
643
S=$(file_size test.r) &&
644
S2=$(file_size test2.r) &&
645
SE=$(file_size error.r) &&
646
+ M=$(git hash-object test.r) &&
647
+ M2=$(git hash-object test2.r) &&
648
+ ME=$(git hash-object error.r) &&
649
+ rm -f debug.log &&
650
651
git add . &&
652
rm -f *.r &&
@@ -637,9 +655,9 @@ test_expect_success PERL 'process filter should not be restarted if it signals a
655
cat >expected.log <<-EOF &&
656
START
657
init handshake complete
640
- IN: smudge error.r $SE [OK] -- [ERROR]
641
- IN: smudge test.r $S [OK] -- OUT: $S . [OK]
642
- IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
658
+ IN: smudge error.r blob=$ME $SE [OK] -- [ERROR]
659
+ IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK]
660
+ IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
661
STOP
662
EOF
663
test_cmp_exclude_clean expected.log debug.log &&
@@ -665,18 +683,21 @@ test_expect_success PERL 'process filter abort stops processing of all further f
683
echo "error this blob and all future blobs" >abort.o &&
684
cp abort.o abort.r &&
685
686
+ M="blob=$(git hash-object abort.r)" &&
687
+ rm -f debug.log &&
688
SA=$(file_size abort.r) &&
689
690
git add . &&
691
rm -f *.r &&
692
693
+
694
# Note: This test assumes that Git filters files in alphabetical
695
# order ("abort.r" before "test.r").
696
filter_git checkout --quiet --no-progress . &&
697
cat >expected.log <<-EOF &&
698
START
699
init handshake complete
679
- IN: smudge abort.r $SA [OK] -- [ABORT]
700
+ IN: smudge abort.r $M $SA [OK] -- [ABORT]
701
STOP
702
EOF
703
test_cmp_exclude_clean expected.log debug.log &&
@@ -727,27 +748,28 @@ test_expect_success PERL 'delayed checkout in process filter' '
748
) &&
749
750
S=$(file_size "$TEST_ROOT/test.o") &&
751
+ M="blob=$(git -C repo rev-parse --verify master:test.a)" &&
752
cat >a.exp <<-EOF &&
753
START
754
init handshake complete
733
- IN: smudge test.a $S [OK] -- OUT: $S . [OK]
734
- IN: smudge test-delay10.a $S [OK] -- [DELAYED]
735
- IN: smudge test-delay11.a $S [OK] -- [DELAYED]
736
- IN: smudge test-delay20.a $S [OK] -- [DELAYED]
755
+ IN: smudge test.a $M $S [OK] -- OUT: $S . [OK]
756
+ IN: smudge test-delay10.a $M $S [OK] -- [DELAYED]
757
+ IN: smudge test-delay11.a $M $S [OK] -- [DELAYED]
758
+ IN: smudge test-delay20.a $M $S [OK] -- [DELAYED]
759
IN: list_available_blobs test-delay10.a test-delay11.a [OK]
738
- IN: smudge test-delay10.a 0 [OK] -- OUT: $S . [OK]
739
- IN: smudge test-delay11.a 0 [OK] -- OUT: $S . [OK]
760
+ IN: smudge test-delay10.a $M 0 [OK] -- OUT: $S . [OK]
761
+ IN: smudge test-delay11.a $M 0 [OK] -- OUT: $S . [OK]
762
IN: list_available_blobs test-delay20.a [OK]
741
- IN: smudge test-delay20.a 0 [OK] -- OUT: $S . [OK]
763
+ IN: smudge test-delay20.a $M 0 [OK] -- OUT: $S . [OK]
764
IN: list_available_blobs [OK]
765
STOP
766
EOF
767
cat >b.exp <<-EOF &&
768
START
769
init handshake complete
748
- IN: smudge test-delay10.b $S [OK] -- [DELAYED]
770
+ IN: smudge test-delay10.b $M $S [OK] -- [DELAYED]
771
IN: list_available_blobs test-delay10.b [OK]
750
- IN: smudge test-delay10.b 0 [OK] -- OUT: $S . [OK]
772
+ IN: smudge test-delay10.b $M 0 [OK] -- OUT: $S . [OK]
773
IN: list_available_blobs [OK]
774
STOP
775
EOF
t/t0021/rot13-filter.pl
+1
-1
@@ -136,7 +136,7 @@ while (1) {
136
$DELAY{$pathname}{"requested"} = 1;
137
}
138
} elsif ($buffer =~ /^(ref|treeish|blob)=/) {
139
- # Do nothing.
139
+ print $debug " $buffer";
140
} else {
141
# In general, filters need to be graceful about
142
# new metadata, since it's documented that we
unpack-trees.c
+1
@@ -371,6 +371,7 @@ static int check_updates(struct unpack_trees_options *o)
371
state.quiet = 1;
372
state.refresh_cache = 1;
373
state.istate = index;
374
+ clone_checkout_metadata(&state.meta, &o->meta, NULL);
375
376
if (!o->update || o->dry_run) {
377
remove_marked_cache_entries(index, 0);
unpack-trees.h
+1
@@ -85,6 +85,7 @@ struct unpack_trees_options {
85
struct index_state result;
86
87
struct pattern_list *pl; /* for internal use */
88
+ struct checkout_metadata meta;
89
};
90
91
int unpack_trees(unsigned n, struct tree_desc *t,