unsigned int length;
} objectname;
struct refname_atom refname;
+ char *head;
} u;
} *used_atom;
static int used_atom_cnt, need_tagged, need_symref;
}
}
+static void head_atom_parser(struct used_atom *atom, const char *arg)
+{
+ struct object_id unused;
+
+ atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, unused.hash, NULL);
+}
static struct {
const char *name;
{ "push", FIELD_STR, remote_ref_atom_parser },
{ "symref", FIELD_STR, refname_atom_parser },
{ "flag" },
- { "HEAD" },
+ { "HEAD", FIELD_STR, head_atom_parser },
{ "color", FIELD_STR, color_atom_parser },
{ "align", FIELD_STR, align_atom_parser },
{ "end" },
struct atom_value {
const char *s;
void (*handler)(struct atom_value *atomv, struct ref_formatting_state *state);
- unsigned long ul; /* used for sorting when not FIELD_STR */
+ uintmax_t value; /* used for sorting when not FIELD_STR */
struct used_atom *atom;
};
* by the "struct object" representation, set *eaten as well---it is a
* signal from parse_object_buffer to us not to free the buffer.
*/
-static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
+static void *get_obj(const struct object_id *oid, struct object **obj, unsigned long *sz, int *eaten)
{
enum object_type type;
- void *buf = read_sha1_file(sha1, &type, sz);
+ void *buf = read_sha1_file(oid->hash, &type, sz);
if (buf)
- *obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
+ *obj = parse_object_buffer(oid, type, *sz, buf, eaten);
else
*obj = NULL;
return buf;
if (!strcmp(name, "objecttype"))
v->s = typename(obj->type);
else if (!strcmp(name, "objectsize")) {
- v->ul = sz;
+ v->value = sz;
v->s = xstrfmt("%lu", sz);
}
else if (deref)
v->s = xstrdup(oid_to_hex(&commit->tree->object.oid));
}
else if (!strcmp(name, "numparent")) {
- v->ul = commit_list_count(commit->parents);
- v->s = xstrfmt("%lu", v->ul);
+ v->value = commit_list_count(commit->parents);
+ v->s = xstrfmt("%lu", (unsigned long)v->value);
}
else if (!strcmp(name, "parent")) {
struct commit_list *parents;
{
const char *eoemail = strstr(buf, "> ");
char *zone;
- unsigned long timestamp;
+ timestamp_t timestamp;
long tz;
struct date_mode date_mode = { DATE_NORMAL };
const char *formatp;
if (!eoemail)
goto bad;
- timestamp = strtoul(eoemail + 2, &zone, 10);
- if (timestamp == ULONG_MAX)
+ timestamp = parse_timestamp(eoemail + 2, &zone, 10);
+ if (timestamp == TIME_MAX)
goto bad;
tz = strtol(zone, NULL, 10);
if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
goto bad;
v->s = xstrdup(show_date(timestamp, tz, &date_mode));
- v->ul = timestamp;
+ v->value = timestamp;
return;
bad:
v->s = "";
- v->ul = 0;
+ v->value = 0;
}
/* See grab_values */
struct object *obj;
int eaten, i;
unsigned long size;
- const unsigned char *tagged;
+ const struct object_id *tagged;
ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
v->s = xstrdup(buf + 1);
}
continue;
- } else if (!deref && grab_objectname(name, ref->objectname, v, atom)) {
+ } else if (!deref && grab_objectname(name, ref->objectname.hash, v, atom)) {
continue;
} else if (!strcmp(name, "HEAD")) {
- const char *head;
- unsigned char sha1[20];
-
- head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- sha1, NULL);
- if (head && !strcmp(ref->refname, head))
+ if (atom->u.head && !strcmp(ref->refname, atom->u.head))
v->s = "*";
else
v->s = " ";
return;
need_obj:
- buf = get_obj(ref->objectname, &obj, &size, &eaten);
+ buf = get_obj(&ref->objectname, &obj, &size, &eaten);
if (!buf)
die(_("missing object %s for %s"),
- sha1_to_hex(ref->objectname), ref->refname);
+ oid_to_hex(&ref->objectname), ref->refname);
if (!obj)
die(_("parse_object_buffer failed on %s for %s"),
- sha1_to_hex(ref->objectname), ref->refname);
+ oid_to_hex(&ref->objectname), ref->refname);
grab_values(ref->value, 0, obj, buf, size);
if (!eaten)
* If it is a tag object, see if we use a value that derefs
* the object, and if we do grab the object it refers to.
*/
- tagged = ((struct tag *)obj)->tagged->oid.hash;
+ tagged = &((struct tag *)obj)->tagged->oid;
/*
* NEEDSWORK: This derefs tag only once, which
buf = get_obj(tagged, &obj, &size, &eaten);
if (!buf)
die(_("missing object %s for %s"),
- sha1_to_hex(tagged), ref->refname);
+ oid_to_hex(tagged), ref->refname);
if (!obj)
die(_("parse_object_buffer failed on %s for %s"),
- sha1_to_hex(tagged), ref->refname);
+ oid_to_hex(tagged), ref->refname);
grab_values(ref->value, 1, obj, buf, size);
if (!eaten)
free(buf);
struct ref_array *array;
struct ref_filter *filter;
struct contains_cache contains_cache;
+ struct contains_cache no_contains_cache;
};
/*
}
static int commit_contains(struct ref_filter *filter, struct commit *commit,
- struct contains_cache *cache)
+ struct commit_list *list, struct contains_cache *cache)
{
if (filter->with_commit_tag_algo)
- return contains_tag_algo(commit, filter->with_commit, cache) == CONTAINS_YES;
- return is_descendant_of(commit, filter->with_commit);
+ return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
+ return is_descendant_of(commit, list);
}
/*
* the need to parse the object via parse_object(). peel_ref() might be a
* more efficient alternative to obtain the pointee.
*/
-static const unsigned char *match_points_at(struct sha1_array *points_at,
- const unsigned char *sha1,
- const char *refname)
+static const struct object_id *match_points_at(struct oid_array *points_at,
+ const struct object_id *oid,
+ const char *refname)
{
- const unsigned char *tagged_sha1 = NULL;
+ const struct object_id *tagged_oid = NULL;
struct object *obj;
- if (sha1_array_lookup(points_at, sha1) >= 0)
- return sha1;
- obj = parse_object(sha1);
+ if (oid_array_lookup(points_at, oid) >= 0)
+ return oid;
+ obj = parse_object(oid);
if (!obj)
die(_("malformed object at '%s'"), refname);
if (obj->type == OBJ_TAG)
- tagged_sha1 = ((struct tag *)obj)->tagged->oid.hash;
- if (tagged_sha1 && sha1_array_lookup(points_at, tagged_sha1) >= 0)
- return tagged_sha1;
+ tagged_oid = &((struct tag *)obj)->tagged->oid;
+ if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0)
+ return tagged_oid;
return NULL;
}
{
struct ref_array_item *ref;
FLEX_ALLOC_STR(ref, refname, refname);
- hashcpy(ref->objectname, objectname);
+ hashcpy(ref->objectname.hash, objectname);
ref->flag = flag;
return ref;
if (!filter_pattern_match(filter, refname))
return 0;
- if (filter->points_at.nr && !match_points_at(&filter->points_at, oid->hash, refname))
+ if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
return 0;
/*
* obtain the commit using the 'oid' available and discard all
* non-commits early. The actual filtering is done later.
*/
- if (filter->merge_commit || filter->with_commit || filter->verbose) {
- commit = lookup_commit_reference_gently(oid->hash, 1);
+ if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) {
+ commit = lookup_commit_reference_gently(oid, 1);
if (!commit)
return 0;
- /* We perform the filtering for the '--contains' option */
+ /* We perform the filtering for the '--contains' option... */
if (filter->with_commit &&
- !commit_contains(filter, commit, &ref_cbdata->contains_cache))
+ !commit_contains(filter, commit, filter->with_commit, &ref_cbdata->contains_cache))
+ return 0;
+ /* ...or for the `--no-contains' option */
+ if (filter->no_commit &&
+ commit_contains(filter, commit, filter->no_commit, &ref_cbdata->no_contains_cache))
return 0;
}
filter->kind = type & FILTER_REFS_KIND_MASK;
init_contains_cache(&ref_cbdata.contains_cache);
+ init_contains_cache(&ref_cbdata.no_contains_cache);
/* Simple per-ref filtering */
if (!filter->kind)
}
clear_contains_cache(&ref_cbdata.contains_cache);
+ clear_contains_cache(&ref_cbdata.no_contains_cache);
/* Filters that need revision walking */
if (filter->merge_commit)
else if (cmp_type == FIELD_STR)
cmp = cmp_fn(va->s, vb->s);
else {
- if (va->ul < vb->ul)
+ if (va->value < vb->value)
cmp = -1;
- else if (va->ul == vb->ul)
+ else if (va->value == vb->value)
cmp = cmp_fn(a->refname, b->refname);
else
cmp = 1;
int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
{
struct ref_filter *rf = opt->value;
- unsigned char sha1[20];
+ struct object_id oid;
+ int no_merged = starts_with(opt->long_name, "no");
+
+ if (rf->merge) {
+ if (no_merged) {
+ return opterror(opt, "is incompatible with --merged", 0);
+ } else {
+ return opterror(opt, "is incompatible with --no-merged", 0);
+ }
+ }
- rf->merge = starts_with(opt->long_name, "no")
+ rf->merge = no_merged
? REF_FILTER_MERGED_OMIT
: REF_FILTER_MERGED_INCLUDE;
- if (get_sha1(arg, sha1))
+ if (get_oid(arg, &oid))
die(_("malformed object name %s"), arg);
- rf->merge_commit = lookup_commit_reference_gently(sha1, 0);
+ rf->merge_commit = lookup_commit_reference_gently(&oid, 0);
if (!rf->merge_commit)
return opterror(opt, "must point to a commit", 0);