Skip to content

Commit c397aac

Browse files
bk2204gitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ab90eca commit c397aac

File tree

10 files changed

+83
-7
lines changed

10 files changed

+83
-7
lines changed

archive.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ void *object_file_to_archive(const struct archiver_args *args,
7777
{
7878
void *buffer;
7979
const struct commit *commit = args->convert ? args->commit : NULL;
80+
struct checkout_metadata meta;
81+
82+
init_checkout_metadata(&meta, args->refname,
83+
args->commit_oid ? args->commit_oid :
84+
(args->tree ? &args->tree->object.oid : NULL), oid);
8085

8186
path += args->baselen;
8287
buffer = read_object_file(oid, type, sizep);
@@ -85,7 +90,7 @@ void *object_file_to_archive(const struct archiver_args *args,
8590
size_t size = 0;
8691

8792
strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
88-
convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, NULL);
93+
convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, &meta);
8994
if (commit)
9095
format_subst(commit, buf.buf, buf.len, &buf);
9196
buffer = strbuf_detach(&buf, &size);
@@ -385,16 +390,17 @@ static void parse_treeish_arg(const char **argv,
385390
struct tree *tree;
386391
const struct commit *commit;
387392
struct object_id oid;
393+
char *ref = NULL;
388394

389395
/* Remotes are only allowed to fetch actual refs */
390396
if (remote && !remote_allow_unreachable) {
391-
char *ref = NULL;
392397
const char *colon = strchrnul(name, ':');
393398
int refnamelen = colon - name;
394399

395400
if (!dwim_ref(name, refnamelen, &oid, &ref))
396401
die(_("no such ref: %.*s"), refnamelen, name);
397-
free(ref);
402+
} else {
403+
dwim_ref(name, strlen(name), &oid, &ref);
398404
}
399405

400406
if (get_oid(name, &oid))
@@ -427,6 +433,7 @@ static void parse_treeish_arg(const char **argv,
427433

428434
tree = parse_tree_indirect(&tree_oid);
429435
}
436+
ar_args->refname = ref;
430437
ar_args->tree = tree;
431438
ar_args->commit_oid = commit_oid;
432439
ar_args->commit = commit;

archive.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct repository;
88

99
struct archiver_args {
1010
struct repository *repo;
11+
const char *refname;
1112
const char *base;
1213
size_t baselen;
1314
struct tree *tree;

builtin/cat-file.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ static int filter_object(const char *path, unsigned mode,
4242
oid_to_hex(oid), path);
4343
if ((type == OBJ_BLOB) && S_ISREG(mode)) {
4444
struct strbuf strbuf = STRBUF_INIT;
45-
if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, NULL)) {
45+
struct checkout_metadata meta;
46+
47+
init_checkout_metadata(&meta, NULL, NULL, oid);
48+
if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, &meta)) {
4649
free(*buf);
4750
*size = strbuf.len;
4851
*buf = strbuf_detach(&strbuf, NULL);

builtin/checkout.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ struct branch_info {
9292
const char *name; /* The short name used */
9393
const char *path; /* The full name of a real branch */
9494
struct commit *commit; /* The named commit */
95+
char *refname; /* The full name of the ref being checked out. */
96+
struct object_id oid; /* The object ID of the commit being checked out. */
9597
/*
9698
* if not null the branch is detached because it's already
9799
* checked out in this checkout
@@ -360,6 +362,10 @@ static int checkout_worktree(const struct checkout_opts *opts,
360362
state.refresh_cache = 1;
361363
state.istate = &the_index;
362364

365+
init_checkout_metadata(&state.meta, info->refname,
366+
info->commit ? &info->commit->object.oid : &info->oid,
367+
NULL);
368+
363369
enable_delayed_checkout(&state);
364370
for (pos = 0; pos < active_nr; pos++) {
365371
struct cache_entry *ce = active_cache[pos];
@@ -636,6 +642,13 @@ static void setup_branch_path(struct branch_info *branch)
636642
{
637643
struct strbuf buf = STRBUF_INIT;
638644

645+
/*
646+
* If this is a ref, resolve it; otherwise, look up the OID for our
647+
* expression. Failure here is okay.
648+
*/
649+
if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname))
650+
repo_get_oid_committish(the_repository, branch->name, &branch->oid);
651+
639652
strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
640653
if (strcmp(buf.buf, branch->name))
641654
branch->name = xstrdup(buf.buf);

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,7 @@ struct checkout {
16791679
const char *base_dir;
16801680
int base_dir_len;
16811681
struct delayed_checkout *delayed_checkout;
1682+
struct checkout_metadata meta;
16821683
unsigned force:1,
16831684
quiet:1,
16841685
not_new:1,

convert.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,3 +2006,25 @@ int stream_filter(struct stream_filter *filter,
20062006
{
20072007
return filter->vtbl->filter(filter, input, isize_p, output, osize_p);
20082008
}
2009+
2010+
void init_checkout_metadata(struct checkout_metadata *meta, const char *refname,
2011+
const struct object_id *treeish,
2012+
const struct object_id *blob)
2013+
{
2014+
memset(meta, 0, sizeof(*meta));
2015+
if (refname)
2016+
meta->refname = refname;
2017+
if (treeish)
2018+
oidcpy(&meta->treeish, treeish);
2019+
if (blob)
2020+
oidcpy(&meta->blob, blob);
2021+
}
2022+
2023+
void clone_checkout_metadata(struct checkout_metadata *dst,
2024+
const struct checkout_metadata *src,
2025+
const struct object_id *blob)
2026+
{
2027+
memcpy(dst, src, sizeof(*dst));
2028+
if (blob)
2029+
oidcpy(&dst->blob, blob);
2030+
}

convert.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,23 @@ void convert_to_git_filter_fd(const struct index_state *istate,
102102
int would_convert_to_git_filter_fd(const struct index_state *istate,
103103
const char *path);
104104

105+
/*
106+
* Initialize the checkout metadata with the given values. Any argument may be
107+
* NULL if it is not applicable. The treeish should be a commit if that is
108+
* available, and a tree otherwise.
109+
*
110+
* The refname is not copied and must be valid for the lifetime of the struct.
111+
* THe object IDs are copied.
112+
*/
113+
void init_checkout_metadata(struct checkout_metadata *meta, const char *refname,
114+
const struct object_id *treeish,
115+
const struct object_id *blob);
116+
117+
/* Copy the metadata from src to dst, updating the blob. */
118+
void clone_checkout_metadata(struct checkout_metadata *dst,
119+
const struct checkout_metadata *src,
120+
const struct object_id *blob);
121+
105122
/*
106123
* Reset the internal list of attributes used by convert_to_git and
107124
* convert_to_working_tree.

diff.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4062,6 +4062,9 @@ static void prep_temp_blob(struct index_state *istate,
40624062
struct strbuf tempfile = STRBUF_INIT;
40634063
char *path_dup = xstrdup(path);
40644064
const char *base = basename(path_dup);
4065+
struct checkout_metadata meta;
4066+
4067+
init_checkout_metadata(&meta, NULL, NULL, oid);
40654068

40664069
/* Generate "XXXXXX_basename.ext" */
40674070
strbuf_addstr(&tempfile, "XXXXXX_");
@@ -4071,7 +4074,7 @@ static void prep_temp_blob(struct index_state *istate,
40714074
if (!temp->tempfile)
40724075
die_errno("unable to create temp-file");
40734076
if (convert_to_working_tree(istate, path,
4074-
(const char *)blob, (size_t)size, &buf, NULL)) {
4077+
(const char *)blob, (size_t)size, &buf, &meta)) {
40754078
blob = buf.buf;
40764079
size = buf.len;
40774080
}

entry.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ static int write_entry(struct cache_entry *ce,
264264
size_t newsize = 0;
265265
struct stat st;
266266
const struct submodule *sub;
267+
struct checkout_metadata meta;
268+
269+
clone_checkout_metadata(&meta, &state->meta, &ce->oid);
267270

268271
if (ce_mode_s_ifmt == S_IFREG) {
269272
struct stream_filter *filter = get_stream_filter(state->istate, ce->name,
@@ -315,13 +318,13 @@ static int write_entry(struct cache_entry *ce,
315318
*/
316319
if (dco && dco->state != CE_NO_DELAY) {
317320
ret = async_convert_to_working_tree(state->istate, ce->name, new_blob,
318-
size, &buf, NULL, dco);
321+
size, &buf, &meta, dco);
319322
if (ret && string_list_has_string(&dco->paths, ce->name)) {
320323
free(new_blob);
321324
goto delayed;
322325
}
323326
} else
324-
ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, NULL);
327+
ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, &meta);
325328

326329
if (ret) {
327330
free(new_blob);

t/t0021/rot13-filter.pl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,13 @@ sub rot13 {
135135
if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) {
136136
$DELAY{$pathname}{"requested"} = 1;
137137
}
138+
} elsif ($buffer =~ /^(ref|treeish|blob)=/) {
139+
# Do nothing.
138140
} else {
141+
# In general, filters need to be graceful about
142+
# new metadata, since it's documented that we
143+
# can pass any key-value pairs, but for tests,
144+
# let's be a little stricter.
139145
die "Unknown message '$buffer'";
140146
}
141147

0 commit comments

Comments
 (0)