#include "parse-options.h"
#include "diff.h"
#include "hash.h"
+#include "argv-array.h"
-#define SEEN (1u<<0)
+#define SEEN (1u << 0)
#define MAX_TAGS (FLAG_BITS - 1)
static const char * const describe_usage[] = {
- N_("git describe [options] <committish>*"),
+ N_("git describe [options] <commit-ish>*"),
N_("git describe [options] --dirty"),
NULL
};
static int all; /* Any valid ref can be used */
static int tags; /* Allow lightweight tags */
static int longformat;
+static int first_parent;
static int abbrev = -1; /* unspecified */
static int max_candidates = 10;
static struct hash_table names;
"diff-index", "--quiet", "HEAD", "--", NULL
};
-
struct commit_name {
struct commit_name *next;
unsigned char peeled[20];
unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
unsigned name_checked:1;
unsigned char sha1[20];
- const char *path;
+ char *path;
};
+
static const char *prio_names[] = {
"head", "lightweight", "annotated",
};
} else {
e->next = NULL;
}
+ e->path = NULL;
}
e->tag = tag;
e->prio = prio;
e->name_checked = 0;
hashcpy(e->sha1, sha1);
- e->path = path;
+ free(e->path);
+ e->path = xstrdup(path);
}
}
static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
- int is_tag = !prefixcmp(path, "refs/tags/");
+ int is_tag = starts_with(path, "refs/tags/");
unsigned char peeled[20];
int is_annotated, prio;
commit_list_insert_by_date(p, &list);
p->object.flags |= c->object.flags;
parents = parents->next;
+
+ if (first_parent)
+ break;
}
}
{
int contains = 0;
struct option options[] = {
- OPT_BOOLEAN(0, "contains", &contains, N_("find the tag that comes after the commit")),
- OPT_BOOLEAN(0, "debug", &debug, N_("debug search strategy on stderr")),
- OPT_BOOLEAN(0, "all", &all, N_("use any ref")),
- OPT_BOOLEAN(0, "tags", &tags, N_("use any tag, even unannotated")),
- OPT_BOOLEAN(0, "long", &longformat, N_("always use long format")),
+ OPT_BOOL(0, "contains", &contains, N_("find the tag that comes after the commit")),
+ OPT_BOOL(0, "debug", &debug, N_("debug search strategy on stderr")),
+ OPT_BOOL(0, "all", &all, N_("use any ref")),
+ OPT_BOOL(0, "tags", &tags, N_("use any tag, even unannotated")),
+ OPT_BOOL(0, "long", &longformat, N_("always use long format")),
+ OPT_BOOL(0, "first-parent", &first_parent, N_("only follow first parent")),
OPT__ABBREV(&abbrev),
OPT_SET_INT(0, "exact-match", &max_candidates,
N_("only output exact matches"), 0),
N_("consider <n> most recent tags (default: 10)")),
OPT_STRING(0, "match", &pattern, N_("pattern"),
N_("only consider tags matching <pattern>")),
- OPT_BOOLEAN(0, "always", &always,
- N_("show abbreviated commit object as fallback")),
+ OPT_BOOL(0, "always", &always,
+ N_("show abbreviated commit object as fallback")),
{OPTION_STRING, 0, "dirty", &dirty, N_("mark"),
- N_("append <mark> on dirty working tree (default: \"-dirty\")"),
- PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
+ N_("append <mark> on dirty working tree (default: \"-dirty\")"),
+ PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
OPT_END(),
};
die(_("--long is incompatible with --abbrev=0"));
if (contains) {
- const char **args = xmalloc((7 + argc) * sizeof(char *));
- int i = 0;
- args[i++] = "name-rev";
- args[i++] = "--name-only";
- args[i++] = "--no-undefined";
+ struct argv_array args;
+
+ argv_array_init(&args);
+ argv_array_pushl(&args, "name-rev",
+ "--peel-tag", "--name-only", "--no-undefined",
+ NULL);
if (always)
- args[i++] = "--always";
+ argv_array_push(&args, "--always");
if (!all) {
- args[i++] = "--tags";
- if (pattern) {
- char *s = xmalloc(strlen("--refs=refs/tags/") + strlen(pattern) + 1);
- sprintf(s, "--refs=refs/tags/%s", pattern);
- args[i++] = s;
- }
+ argv_array_push(&args, "--tags");
+ if (pattern)
+ argv_array_pushf(&args, "--refs=refs/tags/%s", pattern);
}
- memcpy(args + i, argv, argc * sizeof(char *));
- args[i + argc] = NULL;
- return cmd_name_rev(i + argc, args, prefix);
+ while (*argv) {
+ argv_array_push(&args, *argv);
+ argv++;
+ }
+ return cmd_name_rev(args.argc, args.argv, prefix);
}
init_hash(&names);
}
describe("HEAD", 1);
} else if (dirty) {
- die(_("--dirty is incompatible with committishes"));
+ die(_("--dirty is incompatible with commit-ishes"));
} else {
- while (argc-- > 0) {
+ while (argc-- > 0)
describe(*argv++, argc == 0);
- }
}
return 0;
}