From a8604766de8136d78944053aadd74a8c1c87aea9 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Tue, 10 Mar 2020 18:20:39 +0000 Subject: builtin/checkout: pass branch info down to checkout_worktree In the future, we're going to want to use the branch info in checkout_worktree, so let's pass the whole struct branch_info down, not just the revision name. We hoist the definition of struct branch_info so it's in scope. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- builtin/checkout.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'builtin/checkout.c') diff --git a/builtin/checkout.c b/builtin/checkout.c index d6773818b8..8a28f48d67 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -88,6 +88,17 @@ struct checkout_opts { struct tree *source_tree; }; +struct branch_info { + const char *name; /* The short name used */ + const char *path; /* The full name of a real branch */ + struct commit *commit; /* The named commit */ + /* + * if not null the branch is detached because it's already + * checked out in this checkout + */ + char *checkout; +}; + static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit, int changed) { @@ -337,7 +348,8 @@ static void mark_ce_for_checkout_no_overlay(struct cache_entry *ce, } } -static int checkout_worktree(const struct checkout_opts *opts) +static int checkout_worktree(const struct checkout_opts *opts, + const struct branch_info *info) { struct checkout state = CHECKOUT_INIT; int nr_checkouts = 0, nr_unmerged = 0; @@ -396,7 +408,7 @@ static int checkout_worktree(const struct checkout_opts *opts) } static int checkout_paths(const struct checkout_opts *opts, - const char *revision) + const struct branch_info *new_branch_info) { int pos; static char *ps_matched; @@ -462,7 +474,7 @@ static int checkout_paths(const struct checkout_opts *opts, else BUG("either flag must have been set, worktree=%d, index=%d", opts->checkout_worktree, opts->checkout_index); - return run_add_interactive(revision, patch_mode, &opts->pathspec); + return run_add_interactive(new_branch_info->name, patch_mode, &opts->pathspec); } repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR); @@ -523,7 +535,7 @@ static int checkout_paths(const struct checkout_opts *opts, /* Now we are committed to check them out */ if (opts->checkout_worktree) - errs |= checkout_worktree(opts); + errs |= checkout_worktree(opts, new_branch_info); else remove_marked_cache_entries(&the_index, 1); @@ -620,17 +632,6 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, } } -struct branch_info { - const char *name; /* The short name used */ - const char *path; /* The full name of a real branch */ - struct commit *commit; /* The named commit */ - /* - * if not null the branch is detached because it's already - * checked out in this checkout - */ - char *checkout; -}; - static void setup_branch_path(struct branch_info *branch) { struct strbuf buf = STRBUF_INIT; @@ -1710,7 +1711,7 @@ static int checkout_main(int argc, const char **argv, const char *prefix, UNLEAK(opts); if (opts->patch_mode || opts->pathspec.nr) - return checkout_paths(opts, new_branch_info.name); + return checkout_paths(opts, &new_branch_info); else return checkout_branch(opts, &new_branch_info); } -- cgit v1.3 From c397aac02f9f97976f675115aa5df6ca01e26d59 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 16 Mar 2020 18:05:03 +0000 Subject: convert: provide additional metadata to filters Now that we have the codebase wired up to pass any additional metadata to filters, let's collect the additional metadata that we'd like to pass. The two main places we pass this metadata are checkouts and archives. In these two situations, reading HEAD isn't a valid option, since HEAD isn't updated for checkouts until after the working tree is written and archives can accept an arbitrary tree. In other situations, HEAD will usually reflect the refname of the branch in current use. We pass a smaller amount of data in other cases, such as git cat-file, where we can really only logically know about the blob. This commit updates only the parts of the checkout code where we don't use unpack_trees. That function and callers of it will be handled in a future commit. In the archive code, we leak a small amount of memory, since nothing we pass in the archiver argument structure is freed. Signed-off-by: brian m. carlson Signed-off-by: Junio C Hamano --- archive.c | 13 ++++++++++--- archive.h | 1 + builtin/cat-file.c | 5 ++++- builtin/checkout.c | 13 +++++++++++++ cache.h | 1 + convert.c | 22 ++++++++++++++++++++++ convert.h | 17 +++++++++++++++++ diff.c | 5 ++++- entry.c | 7 +++++-- t/t0021/rot13-filter.pl | 6 ++++++ 10 files changed, 83 insertions(+), 7 deletions(-) (limited to 'builtin/checkout.c') diff --git a/archive.c b/archive.c index d9e92cce58..fb39706120 100644 --- a/archive.c +++ b/archive.c @@ -77,6 +77,11 @@ void *object_file_to_archive(const struct archiver_args *args, { void *buffer; const struct commit *commit = args->convert ? args->commit : NULL; + struct checkout_metadata meta; + + init_checkout_metadata(&meta, args->refname, + args->commit_oid ? args->commit_oid : + (args->tree ? &args->tree->object.oid : NULL), oid); path += args->baselen; buffer = read_object_file(oid, type, sizep); @@ -85,7 +90,7 @@ void *object_file_to_archive(const struct archiver_args *args, size_t size = 0; strbuf_attach(&buf, buffer, *sizep, *sizep + 1); - convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, NULL); + convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, &meta); if (commit) format_subst(commit, buf.buf, buf.len, &buf); buffer = strbuf_detach(&buf, &size); @@ -385,16 +390,17 @@ static void parse_treeish_arg(const char **argv, struct tree *tree; const struct commit *commit; struct object_id oid; + char *ref = NULL; /* Remotes are only allowed to fetch actual refs */ if (remote && !remote_allow_unreachable) { - char *ref = NULL; const char *colon = strchrnul(name, ':'); int refnamelen = colon - name; if (!dwim_ref(name, refnamelen, &oid, &ref)) die(_("no such ref: %.*s"), refnamelen, name); - free(ref); + } else { + dwim_ref(name, strlen(name), &oid, &ref); } if (get_oid(name, &oid)) @@ -427,6 +433,7 @@ static void parse_treeish_arg(const char **argv, tree = parse_tree_indirect(&tree_oid); } + ar_args->refname = ref; ar_args->tree = tree; ar_args->commit_oid = commit_oid; ar_args->commit = commit; diff --git a/archive.h b/archive.h index e60e3dd31c..3bd96bf6bb 100644 --- a/archive.h +++ b/archive.h @@ -8,6 +8,7 @@ struct repository; struct archiver_args { struct repository *repo; + const char *refname; const char *base; size_t baselen; struct tree *tree; diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 545fed4924..6ecc8ee6dc 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -42,7 +42,10 @@ static int filter_object(const char *path, unsigned mode, oid_to_hex(oid), path); if ((type == OBJ_BLOB) && S_ISREG(mode)) { struct strbuf strbuf = STRBUF_INIT; - if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, NULL)) { + struct checkout_metadata meta; + + init_checkout_metadata(&meta, NULL, NULL, oid); + if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, &meta)) { free(*buf); *size = strbuf.len; *buf = strbuf_detach(&strbuf, NULL); diff --git a/builtin/checkout.c b/builtin/checkout.c index 8a28f48d67..1bdb70d3dd 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -92,6 +92,8 @@ struct branch_info { const char *name; /* The short name used */ const char *path; /* The full name of a real branch */ struct commit *commit; /* The named commit */ + char *refname; /* The full name of the ref being checked out. */ + struct object_id oid; /* The object ID of the commit being checked out. */ /* * if not null the branch is detached because it's already * checked out in this checkout @@ -360,6 +362,10 @@ static int checkout_worktree(const struct checkout_opts *opts, state.refresh_cache = 1; state.istate = &the_index; + init_checkout_metadata(&state.meta, info->refname, + info->commit ? &info->commit->object.oid : &info->oid, + NULL); + enable_delayed_checkout(&state); for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; @@ -636,6 +642,13 @@ static void setup_branch_path(struct branch_info *branch) { struct strbuf buf = STRBUF_INIT; + /* + * If this is a ref, resolve it; otherwise, look up the OID for our + * expression. Failure here is okay. + */ + if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname)) + repo_get_oid_committish(the_repository, branch->name, &branch->oid); + strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL); if (strcmp(buf.buf, branch->name)) branch->name = xstrdup(buf.buf); diff --git a/cache.h b/cache.h index 37c899b53f..9b24e5d61f 100644 --- a/cache.h +++ b/cache.h @@ -1679,6 +1679,7 @@ struct checkout { const char *base_dir; int base_dir_len; struct delayed_checkout *delayed_checkout; + struct checkout_metadata meta; unsigned force:1, quiet:1, not_new:1, diff --git a/convert.c b/convert.c index 6261921cfb..5aa87d45e3 100644 --- a/convert.c +++ b/convert.c @@ -2006,3 +2006,25 @@ int stream_filter(struct stream_filter *filter, { return filter->vtbl->filter(filter, input, isize_p, output, osize_p); } + +void init_checkout_metadata(struct checkout_metadata *meta, const char *refname, + const struct object_id *treeish, + const struct object_id *blob) +{ + memset(meta, 0, sizeof(*meta)); + if (refname) + meta->refname = refname; + if (treeish) + oidcpy(&meta->treeish, treeish); + if (blob) + oidcpy(&meta->blob, blob); +} + +void clone_checkout_metadata(struct checkout_metadata *dst, + const struct checkout_metadata *src, + const struct object_id *blob) +{ + memcpy(dst, src, sizeof(*dst)); + if (blob) + oidcpy(&dst->blob, blob); +} diff --git a/convert.h b/convert.h index 894e01c38b..e29d1026a6 100644 --- a/convert.h +++ b/convert.h @@ -102,6 +102,23 @@ void convert_to_git_filter_fd(const struct index_state *istate, int would_convert_to_git_filter_fd(const struct index_state *istate, const char *path); +/* + * Initialize the checkout metadata with the given values. Any argument may be + * NULL if it is not applicable. The treeish should be a commit if that is + * available, and a tree otherwise. + * + * The refname is not copied and must be valid for the lifetime of the struct. + * THe object IDs are copied. + */ +void init_checkout_metadata(struct checkout_metadata *meta, const char *refname, + const struct object_id *treeish, + const struct object_id *blob); + +/* Copy the metadata from src to dst, updating the blob. */ +void clone_checkout_metadata(struct checkout_metadata *dst, + const struct checkout_metadata *src, + const struct object_id *blob); + /* * Reset the internal list of attributes used by convert_to_git and * convert_to_working_tree. diff --git a/diff.c b/diff.c index 12761c8017..1010d806f5 100644 --- a/diff.c +++ b/diff.c @@ -4062,6 +4062,9 @@ static void prep_temp_blob(struct index_state *istate, struct strbuf tempfile = STRBUF_INIT; char *path_dup = xstrdup(path); const char *base = basename(path_dup); + struct checkout_metadata meta; + + init_checkout_metadata(&meta, NULL, NULL, oid); /* Generate "XXXXXX_basename.ext" */ strbuf_addstr(&tempfile, "XXXXXX_"); @@ -4071,7 +4074,7 @@ static void prep_temp_blob(struct index_state *istate, if (!temp->tempfile) die_errno("unable to create temp-file"); if (convert_to_working_tree(istate, path, - (const char *)blob, (size_t)size, &buf, NULL)) { + (const char *)blob, (size_t)size, &buf, &meta)) { blob = buf.buf; size = buf.len; } diff --git a/entry.c b/entry.c index 4b2d9b2dad..00b4903366 100644 --- a/entry.c +++ b/entry.c @@ -264,6 +264,9 @@ static int write_entry(struct cache_entry *ce, size_t newsize = 0; struct stat st; const struct submodule *sub; + struct checkout_metadata meta; + + clone_checkout_metadata(&meta, &state->meta, &ce->oid); if (ce_mode_s_ifmt == S_IFREG) { struct stream_filter *filter = get_stream_filter(state->istate, ce->name, @@ -315,13 +318,13 @@ static int write_entry(struct cache_entry *ce, */ if (dco && dco->state != CE_NO_DELAY) { ret = async_convert_to_working_tree(state->istate, ce->name, new_blob, - size, &buf, NULL, dco); + size, &buf, &meta, dco); if (ret && string_list_has_string(&dco->paths, ce->name)) { free(new_blob); goto delayed; } } else - ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, NULL); + ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, &meta); if (ret) { free(new_blob); diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl index 470107248e..c43cf433cf 100644 --- a/t/t0021/rot13-filter.pl +++ b/t/t0021/rot13-filter.pl @@ -135,7 +135,13 @@ while (1) { if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) { $DELAY{$pathname}{"requested"} = 1; } + } elsif ($buffer =~ /^(ref|treeish|blob)=/) { + # Do nothing. } else { + # In general, filters need to be graceful about + # new metadata, since it's documented that we + # can pass any key-value pairs, but for tests, + # let's be a little stricter. die "Unknown message '$buffer'"; } -- cgit v1.3 From 13e7ed6a3a0ecd5d50b7bba2d86ce9d88494fa9b Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 16 Mar 2020 18:05:04 +0000 Subject: 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 Signed-off-by: Junio C Hamano --- builtin/checkout.c | 18 +++++++++--- merge.c | 1 + t/t0021-conversion.sh | 78 +++++++++++++++++++++++++++++++------------------ t/t0021/rot13-filter.pl | 2 +- unpack-trees.c | 1 + unpack-trees.h | 1 + 6 files changed, 68 insertions(+), 33 deletions(-) (limited to 'builtin/checkout.c') diff --git a/builtin/checkout.c b/builtin/checkout.c index 1bdb70d3dd..8bc94d392b 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -604,7 +604,8 @@ static void describe_detached_head(const char *msg, struct commit *commit) } static int reset_tree(struct tree *tree, const struct checkout_opts *o, - int worktree, int *writeout_error) + int worktree, int *writeout_error, + struct branch_info *info) { struct unpack_trees_options opts; struct tree_desc tree_desc; @@ -619,6 +620,11 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o, opts.verbose_update = o->show_progress; opts.src_index = &the_index; opts.dst_index = &the_index; + init_checkout_metadata(&opts.meta, info->refname, + info->commit ? &info->commit->object.oid : + is_null_oid(&info->oid) ? &tree->object.oid : + &info->oid, + NULL); parse_tree(tree); init_tree_desc(&tree_desc, tree->buffer, tree->size); switch (unpack_trees(1, &tree_desc, &opts)) { @@ -677,7 +683,7 @@ static int merge_working_tree(const struct checkout_opts *opts, } else new_tree = get_commit_tree(new_branch_info->commit); if (opts->discard_changes) { - ret = reset_tree(new_tree, opts, 1, writeout_error); + ret = reset_tree(new_tree, opts, 1, writeout_error, new_branch_info); if (ret) return ret; } else { @@ -706,6 +712,10 @@ static int merge_working_tree(const struct checkout_opts *opts, topts.quiet = opts->merge && old_branch_info->commit; topts.verbose_update = opts->show_progress; topts.fn = twoway_merge; + init_checkout_metadata(&topts.meta, new_branch_info->refname, + new_branch_info->commit ? + &new_branch_info->commit->object.oid : + &new_branch_info->oid, NULL); if (opts->overwrite_ignore) { topts.dir = xcalloc(1, sizeof(*topts.dir)); topts.dir->flags |= DIR_SHOW_IGNORED; @@ -776,7 +786,7 @@ static int merge_working_tree(const struct checkout_opts *opts, ret = reset_tree(new_tree, opts, 1, - writeout_error); + writeout_error, new_branch_info); if (ret) return ret; o.ancestor = old_branch_info->name; @@ -796,7 +806,7 @@ static int merge_working_tree(const struct checkout_opts *opts, exit(128); ret = reset_tree(new_tree, opts, 0, - writeout_error); + writeout_error, new_branch_info); strbuf_release(&o.obuf); strbuf_release(&old_commit_shortname); if (ret) diff --git a/merge.c b/merge.c index 7c1d756c3f..aa36de2f64 100644 --- a/merge.c +++ b/merge.c @@ -94,6 +94,7 @@ int checkout_fast_forward(struct repository *r, opts.verbose_update = 1; opts.merge = 1; opts.fn = twoway_merge; + init_checkout_metadata(&opts.meta, NULL, remote, NULL); setup_unpack_trees_porcelain(&opts, "merge"); if (unpack_trees(nr_trees, t, &opts)) { diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index dc664da551..4b8d6a74a7 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -364,6 +364,10 @@ test_expect_success PERL 'required process filter should filter data' ' S=$(file_size test.r) && S2=$(file_size test2.r) && S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") && + EMPTY=$(git hash-object /dev/null) && filter_git add . && cat >expected.log <<-EOF && @@ -378,14 +382,15 @@ test_expect_success PERL 'required process filter should filter data' ' test_cmp_count expected.log debug.log && git commit -m "test commit 2" && + META="ref=refs/heads/master treeish=$(git rev-parse --verify master)" && rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x=.r" && filter_git checkout --quiet --no-progress . && cat >expected.log <<-EOF && START init handshake complete - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] - IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -406,10 +411,10 @@ test_expect_success PERL 'required process filter should filter data' ' cat >expected.log <<-EOF && START init handshake complete - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] - IN: smudge test4-empty.r 0 [OK] -- OUT: 0 [OK] - IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -519,17 +524,22 @@ test_expect_success PERL 'required process filter should process multiple packet EOF test_cmp_count expected.log debug.log && - rm -f *.file && + M1="blob=$(git hash-object 1pkt_1__.file)" && + M2="blob=$(git hash-object 2pkt_1+1.file)" && + M3="blob=$(git hash-object 2pkt_2-1.file)" && + M4="blob=$(git hash-object 2pkt_2__.file)" && + M5="blob=$(git hash-object 3pkt_2+1.file)" && + rm -f *.file debug.log && filter_git checkout --quiet --no-progress -- *.file && cat >expected.log <<-EOF && START init handshake complete - IN: smudge 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK] - IN: smudge 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK] - IN: smudge 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK] - IN: smudge 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK] - IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] + IN: smudge 1pkt_1__.file $M1 $(($S )) [OK] -- OUT: $(($S )) . [OK] + IN: smudge 2pkt_1+1.file $M2 $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK] + IN: smudge 2pkt_2-1.file $M3 $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK] + IN: smudge 2pkt_2__.file $M4 $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK] + IN: smudge 3pkt_2+1.file $M5 $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -578,6 +588,10 @@ test_expect_success PERL 'process filter should restart after unexpected write f S=$(file_size test.r) && S2=$(file_size test2.r) && SF=$(file_size smudge-write-fail.r) && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + MF=$(git hash-object smudge-write-fail.r) && + rm -f debug.log && git add . && rm -f *.r && @@ -591,11 +605,11 @@ test_expect_success PERL 'process filter should restart after unexpected write f cat >expected.log <<-EOF && START init handshake complete - IN: smudge smudge-write-fail.r $SF [OK] -- [WRITE FAIL] + IN: smudge smudge-write-fail.r blob=$MF $SF [OK] -- [WRITE FAIL] START init handshake complete - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] STOP EOF 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 S=$(file_size test.r) && S2=$(file_size test2.r) && SE=$(file_size error.r) && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + ME=$(git hash-object error.r) && + rm -f debug.log && git add . && rm -f *.r && @@ -637,9 +655,9 @@ test_expect_success PERL 'process filter should not be restarted if it signals a cat >expected.log <<-EOF && START init handshake complete - IN: smudge error.r $SE [OK] -- [ERROR] - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge error.r blob=$ME $SE [OK] -- [ERROR] + IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] STOP EOF 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 echo "error this blob and all future blobs" >abort.o && cp abort.o abort.r && + M="blob=$(git hash-object abort.r)" && + rm -f debug.log && SA=$(file_size abort.r) && git add . && rm -f *.r && + # Note: This test assumes that Git filters files in alphabetical # order ("abort.r" before "test.r"). filter_git checkout --quiet --no-progress . && cat >expected.log <<-EOF && START init handshake complete - IN: smudge abort.r $SA [OK] -- [ABORT] + IN: smudge abort.r $M $SA [OK] -- [ABORT] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -727,27 +748,28 @@ test_expect_success PERL 'delayed checkout in process filter' ' ) && S=$(file_size "$TEST_ROOT/test.o") && + M="blob=$(git -C repo rev-parse --verify master:test.a)" && cat >a.exp <<-EOF && START init handshake complete - IN: smudge test.a $S [OK] -- OUT: $S . [OK] - IN: smudge test-delay10.a $S [OK] -- [DELAYED] - IN: smudge test-delay11.a $S [OK] -- [DELAYED] - IN: smudge test-delay20.a $S [OK] -- [DELAYED] + IN: smudge test.a $M $S [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.a $M $S [OK] -- [DELAYED] + IN: smudge test-delay11.a $M $S [OK] -- [DELAYED] + IN: smudge test-delay20.a $M $S [OK] -- [DELAYED] IN: list_available_blobs test-delay10.a test-delay11.a [OK] - IN: smudge test-delay10.a 0 [OK] -- OUT: $S . [OK] - IN: smudge test-delay11.a 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.a $M 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay11.a $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs test-delay20.a [OK] - IN: smudge test-delay20.a 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay20.a $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs [OK] STOP EOF cat >b.exp <<-EOF && START init handshake complete - IN: smudge test-delay10.b $S [OK] -- [DELAYED] + IN: smudge test-delay10.b $M $S [OK] -- [DELAYED] IN: list_available_blobs test-delay10.b [OK] - IN: smudge test-delay10.b 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.b $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs [OK] STOP EOF diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl index c43cf433cf..cd32a82da5 100644 --- a/t/t0021/rot13-filter.pl +++ b/t/t0021/rot13-filter.pl @@ -136,7 +136,7 @@ while (1) { $DELAY{$pathname}{"requested"} = 1; } } elsif ($buffer =~ /^(ref|treeish|blob)=/) { - # Do nothing. + print $debug " $buffer"; } else { # In general, filters need to be graceful about # new metadata, since it's documented that we diff --git a/unpack-trees.c b/unpack-trees.c index 1ecdab3304..3aba5da6b6 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -371,6 +371,7 @@ static int check_updates(struct unpack_trees_options *o) state.quiet = 1; state.refresh_cache = 1; state.istate = index; + clone_checkout_metadata(&state.meta, &o->meta, NULL); if (!o->update || o->dry_run) { remove_marked_cache_entries(index, 0); diff --git a/unpack-trees.h b/unpack-trees.h index ae1557fb80..ad41b45a71 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -85,6 +85,7 @@ struct unpack_trees_options { struct index_state result; struct pattern_list *pl; /* for internal use */ + struct checkout_metadata meta; }; int unpack_trees(unsigned n, struct tree_desc *t, -- cgit v1.3