Skip to content

Commit

Permalink
convert: provide additional metadata to filters
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
bk2204 authored and gitster committed Mar 16, 2020
1 parent ab90eca commit c397aac
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 7 deletions.
13 changes: 10 additions & 3 deletions archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions archive.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct repository;

struct archiver_args {
struct repository *repo;
const char *refname;
const char *base;
size_t baselen;
struct tree *tree;
Expand Down
5 changes: 4 additions & 1 deletion builtin/cat-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 13 additions & 0 deletions builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
22 changes: 22 additions & 0 deletions convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
17 changes: 17 additions & 0 deletions convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 4 additions & 1 deletion diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_");
Expand All @@ -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;
}
Expand Down
7 changes: 5 additions & 2 deletions entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions t/t0021/rot13-filter.pl
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@ sub rot13 {
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'";
}

Expand Down

0 comments on commit c397aac

Please sign in to comment.