#include "tag.h"
#include "refs.h"
#include "builtin.h"
+#include "exec_cmd.h"
#define SEEN (1u<<0)
#define MAX_TAGS (FLAG_BITS - 1)
* If --tags, then any tags are used.
* Otherwise only annotated tags are used.
*/
- if (!strncmp(path, "refs/tags/", 10)) {
+ if (!prefixcmp(path, "refs/tags/")) {
if (object->type == OBJ_TAG)
prio = 2;
else
return 0;
}
+static unsigned long finish_depth_computation(
+ struct commit_list **list,
+ struct possible_tag *best)
+{
+ unsigned long seen_commits = 0;
+ while (*list) {
+ struct commit *c = pop_commit(list);
+ struct commit_list *parents = c->parents;
+ seen_commits++;
+ if (c->object.flags & best->flag_within) {
+ struct commit_list *a = *list;
+ while (a) {
+ struct commit *i = a->item;
+ if (!(i->object.flags & best->flag_within))
+ break;
+ a = a->next;
+ }
+ if (!a)
+ break;
+ } else
+ best->depth++;
+ while (parents) {
+ struct commit *p = parents->item;
+ parse_commit(p);
+ if (!(p->object.flags & SEEN))
+ insert_by_date(p, list);
+ p->object.flags |= c->object.flags;
+ parents = parents->next;
+ }
+ }
+ return seen_commits;
+}
+
static void describe(const char *arg, int last_one)
{
unsigned char sha1[20];
parents = parents->next;
}
}
- free_commit_list(list);
if (!match_cnt)
die("cannot describe '%s'", sha1_to_hex(cmit->object.sha1));
qsort(all_matches, match_cnt, sizeof(all_matches[0]), compare_pt);
+
+ if (gave_up_on) {
+ insert_by_date(gave_up_on, &list);
+ seen_commits--;
+ }
+ seen_commits += finish_depth_computation(&list, &all_matches[0]);
+ free_commit_list(list);
+
if (debug) {
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
struct possible_tag *t = &all_matches[cur_match];
if (abbrev == 0)
printf("%s\n", all_matches[0].name->path );
else
- printf("%s-g%s\n", all_matches[0].name->path,
- find_unique_abbrev(cmit->object.sha1, abbrev));
+ printf("%s-%d-g%s\n", all_matches[0].name->path,
+ all_matches[0].depth,
+ find_unique_abbrev(cmit->object.sha1, abbrev));
if (!last_one)
clear_commit_marks(cmit, -1);
int cmd_describe(int argc, const char **argv, const char *prefix)
{
int i;
+ int contains = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (*arg != '-')
break;
+ else if (!strcmp(arg, "--contains"))
+ contains = 1;
else if (!strcmp(arg, "--debug"))
debug = 1;
else if (!strcmp(arg, "--all"))
all = 1;
else if (!strcmp(arg, "--tags"))
tags = 1;
- else if (!strncmp(arg, "--abbrev=", 9)) {
+ else if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
abbrev = DEFAULT_ABBREV;
}
- else if (!strncmp(arg, "--candidates=", 13)) {
+ else if (!prefixcmp(arg, "--candidates=")) {
max_candidates = strtoul(arg + 13, NULL, 10);
if (max_candidates < 1)
max_candidates = 1;
save_commit_buffer = 0;
+ if (contains) {
+ const char **args = xmalloc((4 + argc - i) * sizeof(char*));
+ args[0] = "name-rev";
+ args[1] = "--name-only";
+ args[2] = "--tags";
+ memcpy(args + 3, argv + i, (argc - i) * sizeof(char*));
+ args[3 + argc - i] = NULL;
+ return cmd_name_rev(3 + argc - i, args, prefix);
+ }
+
if (argc <= i)
describe("HEAD", 1);
else