struct object_id delta_base_oid;
void *content;
+ struct object *maybe_object;
struct object_info info;
} oi, oi_deref;
}
}
+static struct object *get_or_parse_object(struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
+{
+ if (!data->maybe_object) {
+ data->maybe_object = parse_object_buffer(the_repository, &data->oid, data->type,
+ data->size, data->content, eaten);
+ if (!data->maybe_object) {
+ strbuf_addf(err, _("parse_object_buffer failed on %s for %s"),
+ oid_to_hex(&data->oid), refname);
+ return NULL;
+ }
+ }
+
+ return data->maybe_object;
+}
+
/* See grab_values */
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj)
+static int grab_tag_values(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
+ struct tag *tag = NULL;
int i;
- struct tag *tag = (struct tag *) obj;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i].name;
struct atom_value *v = &val[i];
if (!!deref != (*name == '*'))
continue;
+
+ if (!tag) {
+ tag = (struct tag *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!tag)
+ return -1;
+ }
+
if (deref)
name++;
if (atom_type == ATOM_TAG)
else if (atom_type == ATOM_OBJECT && tag->tagged)
v->s = xstrdup(oid_to_hex(&tag->tagged->oid));
}
+
+ return 0;
}
/* See grab_values */
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj)
+static int grab_commit_values(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
int i;
- struct commit *commit = (struct commit *) obj;
+ struct commit *commit = NULL;
for (i = 0; i < used_atom_cnt; i++) {
const char *name = used_atom[i].name;
enum atom_type atom_type = used_atom[i].atom_type;
struct atom_value *v = &val[i];
+
if (!!deref != (*name == '*'))
continue;
if (deref)
name++;
+
+ if (!commit) {
+ commit = (struct commit *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!commit)
+ return -1;
+ }
+
if (atom_type == ATOM_TREE &&
grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i]))
continue;
v->s = strbuf_detach(&s, NULL);
}
}
+
+ return 0;
}
static const char *find_wholine(const char *who, int wholen, const char *buf)
}
}
-static void grab_signature(struct atom_value *val, int deref, struct object *obj)
+static int grab_signature(struct atom_value *val, int deref,
+ struct expand_data *data, const char *refname,
+ struct strbuf *err, int *eaten)
{
int i;
- struct commit *commit = (struct commit *) obj;
+ struct commit *commit = NULL;
struct signature_check sigc = { 0 };
int signature_checked = 0;
continue;
if (!signature_checked) {
+ if (!commit) {
+ commit = (struct commit *) get_or_parse_object(data, refname,
+ err, eaten);
+ if (!commit)
+ return -1;
+ }
+
check_commit_signature(commit, &sigc);
signature_checked = 1;
}
if (signature_checked)
signature_check_clear(&sigc);
+
+ return 0;
}
static void find_subpos(const char *buf,
}
static void grab_describe_values(struct atom_value *val, int deref,
- struct object *obj)
+ struct expand_data *data)
{
- struct commit *commit = (struct commit *)obj;
int i;
for (i = 0; i < used_atom_cnt; i++) {
cmd.git_cmd = 1;
strvec_push(&cmd.args, "describe");
strvec_pushv(&cmd.args, atom->u.describe_args.v);
- strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
+ strvec_push(&cmd.args, oid_to_hex(&data->oid));
if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
error(_("failed to run 'describe'"));
v->s = xstrdup("");
* pointed at by the ref itself; otherwise it is the object the
* ref (which is a tag) refers to.
*/
-static void grab_values(struct atom_value *val, int deref, struct object *obj, struct expand_data *data)
+static int grab_values(struct atom_value *val, int deref, struct expand_data *data,
+ const char *refname, struct strbuf *err, int *eaten)
{
void *buf = data->content;
+ int ret;
- switch (obj->type) {
+ switch (data->type) {
case OBJ_TAG:
- grab_tag_values(val, deref, obj);
+ ret = grab_tag_values(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
grab_sub_body_contents(val, deref, data);
grab_person("tagger", val, deref, buf);
- grab_describe_values(val, deref, obj);
+ grab_describe_values(val, deref, data);
break;
case OBJ_COMMIT:
- grab_commit_values(val, deref, obj);
+ ret = grab_commit_values(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
grab_sub_body_contents(val, deref, data);
grab_person("author", val, deref, buf);
grab_person("committer", val, deref, buf);
- grab_signature(val, deref, obj);
- grab_describe_values(val, deref, obj);
+
+ ret = grab_signature(val, deref, data, refname, err, eaten);
+ if (ret < 0)
+ goto out;
+
+ grab_describe_values(val, deref, data);
break;
case OBJ_TREE:
/* grab_tree_values(val, deref, obj, buf, sz); */
grab_sub_body_contents(val, deref, data);
break;
default:
- die("Eh? Object of type %d?", obj->type);
+ die("Eh? Object of type %d?", data->type);
}
+
+ ret = 0;
+out:
+ return ret;
}
static inline char *copy_advance(char *dst, const char *src)
return show_ref(&atom->u.refname, ref->refname);
}
-static int get_object(struct ref_array_item *ref, int deref, struct object **obj,
+static int get_object(struct ref_array_item *ref, int deref,
struct expand_data *oi, struct strbuf *err)
{
- /* parse_object_buffer() will set eaten to 0 if free() will be needed */
- int eaten = 1;
+ /* parse_object_buffer() will set eaten to 1 if free() will be needed */
+ int eaten = 0;
+ int ret;
+
if (oi->info.contentp) {
/* We need to know that to use parse_object_buffer properly */
oi->info.sizep = &oi->size;
oi->info.typep = &oi->type;
}
+
if (odb_read_object_info_extended(the_repository->objects, &oi->oid, &oi->info,
- OBJECT_INFO_LOOKUP_REPLACE))
- return strbuf_addf_ret(err, -1, _("missing object %s for %s"),
- oid_to_hex(&oi->oid), ref->refname);
+ OBJECT_INFO_LOOKUP_REPLACE)) {
+ ret = strbuf_addf_ret(err, -1, _("missing object %s for %s"),
+ oid_to_hex(&oi->oid), ref->refname);
+ goto out;
+ }
if (oi->info.disk_sizep && oi->disk_size < 0)
BUG("Object size is less than zero.");
if (oi->info.contentp) {
- *obj = parse_object_buffer(the_repository, &oi->oid, oi->type, oi->size, oi->content, &eaten);
- if (!*obj) {
- if (!eaten)
- free(oi->content);
- return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
- oid_to_hex(&oi->oid), ref->refname);
- }
- grab_values(ref->value, deref, *obj, oi);
+ ret = grab_values(ref->value, deref, oi, ref->refname, err, &eaten);
+ if (ret < 0)
+ goto out;
}
grab_common_values(ref->value, deref, oi);
+ ret = 0;
+
+out:
if (!eaten)
free(oi->content);
- return 0;
+ return ret;
}
static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees)
*/
static int populate_value(struct ref_array_item *ref, struct strbuf *err)
{
- struct object *obj;
int i;
struct object_info empty = OBJECT_INFO_INIT;
int ahead_behind_atoms = 0;
oi.oid = ref->objectname;
- if (get_object(ref, 0, &obj, &oi, err))
+ if (get_object(ref, 0, &oi, err))
return -1;
/*
* If there is no atom that wants to know about tagged
* object, we are done.
*/
- if (!need_tagged || (obj->type != OBJ_TAG))
+ if (!need_tagged || (oi.type != OBJ_TAG))
return 0;
/*
}
}
- return get_object(ref, 1, &obj, &oi_deref, err);
+ return get_object(ref, 1, &oi_deref, err);
}
/*