X-Git-Url: https://git.octo.it/?p=git.git;a=blobdiff_plain;f=revision.c;h=6a6952cd559af89d3c8dc2c477ddd8c25b470d66;hp=113dd5a89fc03ff17b04443f2ac7148b4c36af33;hb=162f41292167a800432fc6bbacfcd9f93a90b0c8;hpb=b8950769b8b91d634ec549fd1af792ccc1864f79 diff --git a/revision.c b/revision.c index 113dd5a8..6a6952cd 100644 --- a/revision.c +++ b/revision.c @@ -53,8 +53,9 @@ static void mark_blob_uninteresting(struct blob *blob) void mark_tree_uninteresting(struct tree *tree) { + struct tree_desc desc; + struct name_entry entry; struct object *obj = &tree->object; - struct tree_entry_list *entry; if (obj->flags & UNINTERESTING) return; @@ -63,17 +64,22 @@ void mark_tree_uninteresting(struct tree *tree) return; if (parse_tree(tree) < 0) die("bad tree %s", sha1_to_hex(obj->sha1)); - entry = tree->entries; - tree->entries = NULL; - while (entry) { - struct tree_entry_list *next = entry->next; - if (entry->directory) - mark_tree_uninteresting(entry->item.tree); + + desc.buf = tree->buffer; + desc.size = tree->size; + while (tree_entry(&desc, &entry)) { + if (S_ISDIR(entry.mode)) + mark_tree_uninteresting(lookup_tree(entry.sha1)); else - mark_blob_uninteresting(entry->item.blob); - free(entry); - entry = next; + mark_blob_uninteresting(lookup_blob(entry.sha1)); } + + /* + * We don't care about the tree any more + * after it has been marked uninteresting. + */ + free(tree->buffer); + tree->buffer = NULL; } void mark_parents_uninteresting(struct commit *commit) @@ -477,6 +483,36 @@ static void handle_all(struct rev_info *revs, unsigned flags) for_each_ref(handle_one_ref); } +static int add_parents_only(struct rev_info *revs, const char *arg, int flags) +{ + unsigned char sha1[20]; + struct object *it; + struct commit *commit; + struct commit_list *parents; + + if (*arg == '^') { + flags ^= UNINTERESTING; + arg++; + } + if (get_sha1(arg, sha1)) + return 0; + while (1) { + it = get_reference(revs, arg, sha1, 0); + if (strcmp(it->type, tag_type)) + break; + memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20); + } + if (strcmp(it->type, commit_type)) + return 0; + commit = (struct commit *)it; + for (parents = commit->parents; parents; parents = parents->next) { + it = &parents->item->object; + it->flags |= flags; + add_pending_object(revs, it, arg); + } + return 1; +} + void init_revisions(struct rev_info *revs) { memset(revs, 0, sizeof(*revs)); @@ -544,7 +580,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->max_count = atoi(arg + 12); continue; } - /* accept -, like traditilnal "head" */ + /* accept -, like traditional "head" */ if ((*arg == '-') && isdigit(arg[1])) { revs->max_count = atoi(arg + 1); continue; @@ -664,6 +700,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch } if (!strcmp(arg, "-c")) { revs->diff = 1; + revs->dense_combined_merges = 0; revs->combine_merges = 1; continue; } @@ -702,6 +739,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->abbrev = DEFAULT_ABBREV; continue; } + if (!strncmp(arg, "--abbrev=", 9)) { + revs->abbrev = strtoul(arg + 9, NULL, 10); + if (revs->abbrev < MINIMUM_ABBREV) + revs->abbrev = MINIMUM_ABBREV; + else if (revs->abbrev > 40) + revs->abbrev = 40; + continue; + } if (!strcmp(arg, "--abbrev-commit")) { revs->abbrev_commit = 1; continue; @@ -740,39 +785,56 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch include = get_reference(revs, next, sha1, flags); if (!exclude || !include) die("Invalid revision range %s..%s", arg, next); + + if (!seen_dashdash) { + *dotdot = '.'; + verify_non_filename(revs->prefix, arg); + } add_pending_object(revs, exclude, this); add_pending_object(revs, include, next); continue; } *dotdot = '.'; } + dotdot = strstr(arg, "^@"); + if (dotdot && !dotdot[2]) { + *dotdot = 0; + if (add_parents_only(revs, arg, flags)) + continue; + *dotdot = '^'; + } local_flags = 0; if (*arg == '^') { local_flags = UNINTERESTING; arg++; } - if (get_sha1(arg, sha1) < 0) { - struct stat st; + if (get_sha1(arg, sha1)) { int j; if (seen_dashdash || local_flags) die("bad revision '%s'", arg); - /* If we didn't have a "--", all filenames must exist */ - for (j = i; j < argc; j++) { - if (lstat(argv[j], &st) < 0) - die("'%s': %s", argv[j], strerror(errno)); - } + /* If we didn't have a "--": + * (1) all filenames must exist; + * (2) all rev-args must not be interpretable + * as a valid filename. + * but the latter we have checked in the main loop. + */ + for (j = i; j < argc; j++) + verify_filename(revs->prefix, argv[j]); + revs->prune_data = get_pathspec(revs->prefix, argv + i); break; } + if (!seen_dashdash) + verify_non_filename(revs->prefix, arg); object = get_reference(revs, arg, sha1, flags ^ local_flags); add_pending_object(revs, object, arg); } if (def && !revs->pending_objects) { unsigned char sha1[20]; struct object *object; - if (get_sha1(def, sha1) < 0) + if (get_sha1(def, sha1)) die("bad default revision '%s'", def); object = get_reference(revs, def, sha1, 0); add_pending_object(revs, object, def); @@ -789,7 +851,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch } if (revs->combine_merges) { revs->ignore_merges = 0; - if (revs->dense_combined_merges) + if (revs->dense_combined_merges && + (revs->diffopt.output_format != DIFF_FORMAT_DIFFSTAT)) revs->diffopt.output_format = DIFF_FORMAT_PATCH; } revs->diffopt.abbrev = revs->abbrev;