diff options
Diffstat (limited to 'builtin')
48 files changed, 635 insertions, 572 deletions
diff --git a/builtin/apply.c b/builtin/apply.c index ef32e4f624..b0d0986226 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -1409,10 +1409,10 @@ static void recount_diff(const char *line, int size, struct fragment *fragment) case '\\': continue; case '@': - ret = size < 3 || prefixcmp(line, "@@ "); + ret = size < 3 || !starts_with(line, "@@ "); break; case 'd': - ret = size < 5 || prefixcmp(line, "diff "); + ret = size < 5 || !starts_with(line, "diff "); break; default: ret = -1; @@ -1798,11 +1798,11 @@ static struct fragment *parse_binary_hunk(char **buf_p, *status_p = 0; - if (!prefixcmp(buffer, "delta ")) { + if (starts_with(buffer, "delta ")) { patch_method = BINARY_DELTA_DEFLATED; origlen = strtoul(buffer + 6, NULL, 10); } - else if (!prefixcmp(buffer, "literal ")) { + else if (starts_with(buffer, "literal ")) { patch_method = BINARY_LITERAL_DEFLATED; origlen = strtoul(buffer + 8, NULL, 10); } @@ -3627,12 +3627,12 @@ static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20 hunk->oldpos == 1 && hunk->oldlines == 1 && /* does preimage begin with the heading? */ (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL && - !prefixcmp(++preimage, heading) && + starts_with(++preimage, heading) && /* does it record full SHA-1? */ !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) && preimage[sizeof(heading) + 40 - 1] == '\n' && /* does the abbreviated name on the index line agree with it? */ - !prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) + starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix)) return 0; /* it all looks fine */ /* we may have full object name on the index line */ diff --git a/builtin/archive.c b/builtin/archive.c index 49178f159e..a1e3b940c2 100644 --- a/builtin/archive.c +++ b/builtin/archive.c @@ -57,9 +57,9 @@ static int run_remote_archiver(int argc, const char **argv, if (!buf) die(_("git archive: expected ACK/NAK, got EOF")); if (strcmp(buf, "ACK")) { - if (!prefixcmp(buf, "NACK ")) + if (starts_with(buf, "NACK ")) die(_("git archive: NACK %s"), buf + 5); - if (!prefixcmp(buf, "ERR ")) + if (starts_with(buf, "ERR ")) die(_("remote error: %s"), buf + 4); die(_("git archive: protocol error")); } diff --git a/builtin/branch.c b/builtin/branch.c index 636a16ea4e..b4d771673e 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -81,13 +81,13 @@ static int parse_branch_color_slot(const char *var, int ofs) static int git_branch_config(const char *var, const char *value, void *cb) { - if (!prefixcmp(var, "column.")) + if (starts_with(var, "column.")) return git_column_config(var, value, "branch", &colopts); if (!strcmp(var, "color.branch")) { branch_use_color = git_config_colorbool(var, value); return 0; } - if (!prefixcmp(var, "color.branch.")) { + if (starts_with(var, "color.branch.")) { int slot = parse_branch_color_slot(var, 13); if (slot < 0) return 0; @@ -868,7 +868,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (!strcmp(head, "HEAD")) { detached = 1; } else { - if (prefixcmp(head, "refs/heads/")) + if (!starts_with(head, "refs/heads/")) die(_("HEAD not found below refs/heads!")); head += 11; } diff --git a/builtin/cat-file.c b/builtin/cat-file.c index b2ca775a80..f8288c830c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -193,25 +193,28 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data) return end - start + 1; } -static void print_object_or_die(int fd, const unsigned char *sha1, - enum object_type type, unsigned long size) +static void print_object_or_die(int fd, struct expand_data *data) { - if (type == OBJ_BLOB) { + const unsigned char *sha1 = data->sha1; + + assert(data->info.typep); + + if (data->type == OBJ_BLOB) { if (stream_blob_to_fd(fd, sha1, NULL, 0) < 0) die("unable to stream %s to stdout", sha1_to_hex(sha1)); } else { - enum object_type rtype; - unsigned long rsize; + enum object_type type; + unsigned long size; void *contents; - contents = read_sha1_file(sha1, &rtype, &rsize); + contents = read_sha1_file(sha1, &type, &size); if (!contents) die("object %s disappeared", sha1_to_hex(sha1)); - if (rtype != type) + if (type != data->type) die("object %s changed type!?", sha1_to_hex(sha1)); - if (rsize != size) - die("object %s change size!?", sha1_to_hex(sha1)); + if (data->info.sizep && size != data->size) + die("object %s changed size!?", sha1_to_hex(sha1)); write_or_die(fd, contents, size); free(contents); @@ -250,7 +253,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt, strbuf_release(&buf); if (opt->print_contents) { - print_object_or_die(1, data->sha1, data->type, data->size); + print_object_or_die(1, data); write_or_die(1, "\n", 1); } return 0; @@ -275,6 +278,13 @@ static int batch_objects(struct batch_options *opt) data.mark_query = 0; /* + * If we are printing out the object, then always fill in the type, + * since we will want to decide whether or not to stream. + */ + if (opt->print_contents) + data.info.typep = &data.type; + + /* * We are going to call get_sha1 on a potentially very large number of * objects. In most large cases, these will be actual object sha1s. The * cost to double-check that each one is not also a ref (just so we can diff --git a/builtin/checkout.c b/builtin/checkout.c index 904fd715f0..5df3837e31 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -781,7 +781,7 @@ static int switch_branches(const struct checkout_opts *opts, if (!(flag & REF_ISSYMREF)) old.path = NULL; - if (old.path && !prefixcmp(old.path, "refs/heads/")) + if (old.path && starts_with(old.path, "refs/heads/")) old.name = old.path + strlen("refs/heads/"); if (!new->name) { @@ -816,7 +816,7 @@ static int git_checkout_config(const char *var, const char *value, void *cb) return 0; } - if (!prefixcmp(var, "submodule.")) + if (starts_with(var, "submodule.")) return parse_submodule_config_option(var, value); return git_xmerge_config(var, value, NULL); @@ -1151,9 +1151,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) const char *argv0 = argv[0]; if (!argc || !strcmp(argv0, "--")) die (_("--track needs a branch name")); - if (!prefixcmp(argv0, "refs/")) + if (starts_with(argv0, "refs/")) argv0 += 5; - if (!prefixcmp(argv0, "remotes/")) + if (starts_with(argv0, "remotes/")) argv0 += 8; argv0 = strchr(argv0, '/'); if (!argv0 || !argv0[1]) diff --git a/builtin/clean.c b/builtin/clean.c index 615cd57caf..2f26297142 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -100,7 +100,7 @@ static int parse_clean_color_slot(const char *var) static int git_clean_config(const char *var, const char *value, void *cb) { - if (!prefixcmp(var, "column.")) + if (starts_with(var, "column.")) return git_column_config(var, value, "clean", &colopts); /* honors the color.interactive* config variables which also @@ -109,7 +109,7 @@ static int git_clean_config(const char *var, const char *value, void *cb) clean_use_color = git_config_colorbool(var, value); return 0; } - if (!prefixcmp(var, "color.interactive.")) { + if (starts_with(var, "color.interactive.")) { int slot = parse_clean_color_slot(var + strlen("color.interactive.")); if (slot < 0) diff --git a/builtin/clone.c b/builtin/clone.c index 874e0fd0b6..f98f52980d 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -508,9 +508,9 @@ static void write_followtags(const struct ref *refs, const char *msg) { const struct ref *ref; for (ref = refs; ref; ref = ref->next) { - if (prefixcmp(ref->name, "refs/tags/")) + if (!starts_with(ref->name, "refs/tags/")) continue; - if (!suffixcmp(ref->name, "^{}")) + if (ends_with(ref->name, "^{}")) continue; if (!has_sha1_file(ref->old_sha1)) continue; @@ -578,7 +578,7 @@ static void update_remote_refs(const struct ref *refs, static void update_head(const struct ref *our, const struct ref *remote, const char *msg) { - if (our && !prefixcmp(our->name, "refs/heads/")) { + if (our && starts_with(our->name, "refs/heads/")) { /* Local default branch link */ create_symref("HEAD", our->name, NULL); if (!option_bare) { @@ -625,7 +625,7 @@ static int checkout(void) if (advice_detached_head) detach_advice(sha1_to_hex(sha1)); } else { - if (prefixcmp(head, "refs/heads/")) + if (!starts_with(head, "refs/heads/")) die(_("HEAD not found below refs/heads!")); } free(head); @@ -796,6 +796,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (option_local > 0 && !is_local) warning(_("--local is ignored")); + /* no need to be strict, transport_set_option() will validate it again */ + if (option_depth && atoi(option_depth) < 1) + die(_("depth %s is not a positive number"), option_depth); + if (argc == 2) dir = xstrdup(argv[1]); else diff --git a/builtin/column.c b/builtin/column.c index e125a55fc9..75818520e1 100644 --- a/builtin/column.c +++ b/builtin/column.c @@ -34,7 +34,7 @@ int cmd_column(int argc, const char **argv, const char *prefix) }; /* This one is special and must be the first one */ - if (argc > 1 && !prefixcmp(argv[1], "--command=")) { + if (argc > 1 && starts_with(argv[1], "--command=")) { command = argv[1] + 10; git_config(column_config, (void *)command); } else diff --git a/builtin/commit.c b/builtin/commit.c index e89c519192..3767478c6d 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -733,7 +733,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, eol = nl - sb.buf; else eol = sb.len; - if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) { + if (starts_with(sb.buf + previous, "\nConflicts:\n")) { ignore_footer = sb.len - previous; break; } @@ -904,7 +904,7 @@ static int rest_is_empty(struct strbuf *sb, int start) eol = sb->len; if (strlen(sign_off_header) <= eol - i && - !prefixcmp(sb->buf + i, sign_off_header)) { + starts_with(sb->buf + i, sign_off_header)) { i = eol; continue; } @@ -1183,7 +1183,7 @@ static int git_status_config(const char *k, const char *v, void *cb) { struct wt_status *s = cb; - if (!prefixcmp(k, "column.")) + if (starts_with(k, "column.")) return git_column_config(k, v, "status", &s->colopts); if (!strcmp(k, "status.submodulesummary")) { int is_bool; @@ -1211,7 +1211,7 @@ static int git_status_config(const char *k, const char *v, void *cb) s->display_comment_prefix = git_config_bool(k, v); return 0; } - if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) { + if (starts_with(k, "status.color.") || starts_with(k, "color.status.")) { int slot = parse_status_slot(k, 13); if (slot < 0) return 0; @@ -1377,7 +1377,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1, head = resolve_ref_unsafe("HEAD", junk_sha1, 0, NULL); printf("[%s%s ", - !prefixcmp(head, "refs/heads/") ? + starts_with(head, "refs/heads/") ? head + 11 : !strcmp(head, "HEAD") ? _("detached HEAD") : @@ -1505,7 +1505,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) struct strbuf sb = STRBUF_INIT; struct strbuf author_ident = STRBUF_INIT; const char *index_file, *reflog_msg; - char *nl, *p; + char *nl; unsigned char sha1[20]; struct ref_lock *ref_lock; struct commit_list *parents = NULL, **pptr = &parents; @@ -1601,11 +1601,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) } /* Truncate the message just before the diff, if any. */ - if (verbose) { - p = strstr(sb.buf, "\ndiff --git "); - if (p != NULL) - strbuf_setlen(&sb, p - sb.buf + 1); - } + if (verbose) + wt_status_truncate_message_at_cut_line(&sb); if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, cleanup_mode == CLEANUP_ALL); diff --git a/builtin/config.c b/builtin/config.c index 20e89fe4e0..92ebf23f0a 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -671,9 +671,3 @@ int cmd_config(int argc, const char **argv, const char *prefix) return 0; } - -int cmd_repo_config(int argc, const char **argv, const char *prefix) -{ - fprintf(stderr, "WARNING: git repo-config is deprecated in favor of git config.\n"); - return cmd_config(argc, argv, prefix); -} diff --git a/builtin/describe.c b/builtin/describe.c index 6f62109887..7db43dae1b 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -141,7 +141,7 @@ static void add_to_known_names(const char *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; diff --git a/builtin/diff.c b/builtin/diff.c index fe0cc7f1b5..0f247d2400 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -16,6 +16,9 @@ #include "submodule.h" #include "sha1-array.h" +#define DIFF_NO_INDEX_EXPLICIT 1 +#define DIFF_NO_INDEX_IMPLICIT 2 + struct blobinfo { unsigned char sha1[20]; const char *name; @@ -259,7 +262,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) struct object_array ent = OBJECT_ARRAY_INIT; int blobs = 0, paths = 0; struct blobinfo blob[2]; - int nongit; + int nongit = 0, no_index = 0; int result = 0; /* @@ -285,14 +288,59 @@ int cmd_diff(int argc, const char **argv, const char *prefix) * Other cases are errors. */ - prefix = setup_git_directory_gently(&nongit); - gitmodules_config(); + /* Were we asked to do --no-index explicitly? */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + i++; + break; + } + if (!strcmp(argv[i], "--no-index")) + no_index = DIFF_NO_INDEX_EXPLICIT; + if (argv[i][0] != '-') + break; + } + + if (!no_index) + prefix = setup_git_directory_gently(&nongit); + + /* + * Treat git diff with at least one path outside of the + * repo the same as if the command would have been executed + * outside of a git repository. In this case it behaves + * the same way as "git diff --no-index <a> <b>", which acts + * as a colourful "diff" replacement. + */ + if (nongit || ((argc == i + 2) && + (!path_inside_repo(prefix, argv[i]) || + !path_inside_repo(prefix, argv[i + 1])))) + no_index = DIFF_NO_INDEX_IMPLICIT; + + if (!no_index) + gitmodules_config(); git_config(git_diff_ui_config, NULL); init_revisions(&rev, prefix); - /* If this is a no-index diff, just run it and exit there. */ - diff_no_index(&rev, argc, argv, nongit, prefix); + if (no_index && argc != i + 2) { + if (no_index == DIFF_NO_INDEX_IMPLICIT) { + /* + * There was no --no-index and there were not two + * paths. It is possible that the user intended + * to do an inside-repository operation. + */ + fprintf(stderr, "Not a git repository\n"); + fprintf(stderr, + "To compare two paths outside a working tree:\n"); + } + /* Give the usage message for non-repository usage and exit. */ + usagef("git diff %s <path> <path>", + no_index == DIFF_NO_INDEX_EXPLICIT ? + "--no-index" : "[--no-index]"); + + } + if (no_index) + /* If this is a no-index diff, just run it and exit there. */ + diff_no_index(&rev, argc, argv, prefix); /* Otherwise, we are doing the usual "git" diff */ rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; diff --git a/builtin/fast-export.c b/builtin/fast-export.c index ea6305258d..b8d8a3aaf9 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -476,7 +476,7 @@ static void handle_tag(const char *name, struct tag *tag) } } - if (!prefixcmp(name, "refs/tags/")) + if (starts_with(name, "refs/tags/")) name += 10; printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n", name, tagged_mark, diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index c8e858232a..8b8978a252 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -7,7 +7,7 @@ static const char fetch_pack_usage[] = "git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] " "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] " -"[--no-progress] [-v] [<host>:]<directory> [<refs>...]"; +"[--no-progress] [--diag-url] [-v] [<host>:]<directory> [<refs>...]"; static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc, const char *name, int namelen) @@ -48,11 +48,11 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) for (i = 1; i < argc && *argv[i] == '-'; i++) { const char *arg = argv[i]; - if (!prefixcmp(arg, "--upload-pack=")) { + if (starts_with(arg, "--upload-pack=")) { args.uploadpack = arg + 14; continue; } - if (!prefixcmp(arg, "--exec=")) { + if (starts_with(arg, "--exec=")) { args.uploadpack = arg + 7; continue; } @@ -81,11 +81,15 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.stdin_refs = 1; continue; } + if (!strcmp("--diag-url", arg)) { + args.diag_url = 1; + continue; + } if (!strcmp("-v", arg)) { args.verbose = 1; continue; } - if (!prefixcmp(arg, "--depth=")) { + if (starts_with(arg, "--depth=")) { args.depth = strtol(arg + 8, NULL, 0); continue; } @@ -146,10 +150,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) fd[0] = 0; fd[1] = 1; } else { + int flags = args.verbose ? CONNECT_VERBOSE : 0; + if (args.diag_url) + flags |= CONNECT_DIAG_URL; conn = git_connect(fd, dest, args.uploadpack, - args.verbose ? CONNECT_VERBOSE : 0); + flags); + if (!conn) + return args.diag_url ? 0 : 1; } - get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL); ref = fetch_pack(&args, fd, conn, ref, dest, diff --git a/builtin/fetch.c b/builtin/fetch.c index bd7a10164f..1e7d617f46 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -160,48 +160,156 @@ static void add_merge_config(struct ref **head, } } +static int add_existing(const char *refname, const unsigned char *sha1, + int flag, void *cbdata) +{ + struct string_list *list = (struct string_list *)cbdata; + struct string_list_item *item = string_list_insert(list, refname); + item->util = xmalloc(20); + hashcpy(item->util, sha1); + return 0; +} + +static int will_fetch(struct ref **head, const unsigned char *sha1) +{ + struct ref *rm = *head; + while (rm) { + if (!hashcmp(rm->old_sha1, sha1)) + return 1; + rm = rm->next; + } + return 0; +} + static void find_non_local_tags(struct transport *transport, struct ref **head, - struct ref ***tail); + struct ref ***tail) +{ + struct string_list existing_refs = STRING_LIST_INIT_DUP; + struct string_list remote_refs = STRING_LIST_INIT_NODUP; + const struct ref *ref; + struct string_list_item *item = NULL; + + for_each_ref(add_existing, &existing_refs); + for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { + if (!starts_with(ref->name, "refs/tags/")) + continue; + + /* + * The peeled ref always follows the matching base + * ref, so if we see a peeled ref that we don't want + * to fetch then we can mark the ref entry in the list + * as one to ignore by setting util to NULL. + */ + if (ends_with(ref->name, "^{}")) { + if (item && !has_sha1_file(ref->old_sha1) && + !will_fetch(head, ref->old_sha1) && + !has_sha1_file(item->util) && + !will_fetch(head, item->util)) + item->util = NULL; + item = NULL; + continue; + } + + /* + * If item is non-NULL here, then we previously saw a + * ref not followed by a peeled reference, so we need + * to check if it is a lightweight tag that we want to + * fetch. + */ + if (item && !has_sha1_file(item->util) && + !will_fetch(head, item->util)) + item->util = NULL; + + item = NULL; + + /* skip duplicates and refs that we already have */ + if (string_list_has_string(&remote_refs, ref->name) || + string_list_has_string(&existing_refs, ref->name)) + continue; + + item = string_list_insert(&remote_refs, ref->name); + item->util = (void *)ref->old_sha1; + } + string_list_clear(&existing_refs, 1); + + /* + * We may have a final lightweight tag that needs to be + * checked to see if it needs fetching. + */ + if (item && !has_sha1_file(item->util) && + !will_fetch(head, item->util)) + item->util = NULL; + + /* + * For all the tags in the remote_refs string list, + * add them to the list of refs to be fetched + */ + for_each_string_list_item(item, &remote_refs) { + /* Unless we have already decided to ignore this item... */ + if (item->util) + { + struct ref *rm = alloc_ref(item->string); + rm->peer_ref = alloc_ref(item->string); + hashcpy(rm->old_sha1, item->util); + **tail = rm; + *tail = &rm->next; + } + } + + string_list_clear(&remote_refs, 0); +} static struct ref *get_ref_map(struct transport *transport, - struct refspec *refs, int ref_count, int tags, - int *autotags) + struct refspec *refspecs, int refspec_count, + int tags, int *autotags) { int i; struct ref *rm; struct ref *ref_map = NULL; struct ref **tail = &ref_map; - const struct ref *remote_refs = transport_get_remote_refs(transport); + /* opportunistically-updated references: */ + struct ref *orefs = NULL, **oref_tail = &orefs; - if (ref_count || tags == TAGS_SET) { - struct ref **old_tail; + const struct ref *remote_refs = transport_get_remote_refs(transport); - for (i = 0; i < ref_count; i++) { - get_fetch_map(remote_refs, &refs[i], &tail, 0); - if (refs[i].dst && refs[i].dst[0]) + if (refspec_count) { + for (i = 0; i < refspec_count; i++) { + get_fetch_map(remote_refs, &refspecs[i], &tail, 0); + if (refspecs[i].dst && refspecs[i].dst[0]) *autotags = 1; } - /* Merge everything on the command line, but not --tags */ + /* Merge everything on the command line (but not --tags) */ for (rm = ref_map; rm; rm = rm->next) rm->fetch_head_status = FETCH_HEAD_MERGE; - if (tags == TAGS_SET) - get_fetch_map(remote_refs, tag_refspec, &tail, 0); /* - * For any refs that we happen to be fetching via command-line - * arguments, take the opportunity to update their configured - * counterparts. However, we do not want to mention these - * entries in FETCH_HEAD at all, as they would simply be - * duplicates of existing entries. + * For any refs that we happen to be fetching via + * command-line arguments, the destination ref might + * have been missing or have been different than the + * remote-tracking ref that would be derived from the + * configured refspec. In these cases, we want to + * take the opportunity to update their configured + * remote-tracking reference. However, we do not want + * to mention these entries in FETCH_HEAD at all, as + * they would simply be duplicates of existing + * entries, so we set them FETCH_HEAD_IGNORE below. + * + * We compute these entries now, based only on the + * refspecs specified on the command line. But we add + * them to the list following the refspecs resulting + * from the tags option so that one of the latter, + * which has FETCH_HEAD_NOT_FOR_MERGE, is not removed + * by ref_remove_duplicates() in favor of one of these + * opportunistic entries with FETCH_HEAD_IGNORE. */ - old_tail = tail; for (i = 0; i < transport->remote->fetch_refspec_nr; i++) get_fetch_map(ref_map, &transport->remote->fetch[i], - &tail, 1); - for (rm = *old_tail; rm; rm = rm->next) - rm->fetch_head_status = FETCH_HEAD_IGNORE; + &oref_tail, 1); + + if (tags == TAGS_SET) + get_fetch_map(remote_refs, tag_refspec, &tail, 0); } else { /* Use the defaults */ struct remote *remote = transport->remote; @@ -238,11 +346,21 @@ static struct ref *get_ref_map(struct transport *transport, tail = &ref_map->next; } } - if (tags == TAGS_DEFAULT && *autotags) + + if (tags == TAGS_SET) + /* also fetch all tags */ + get_fetch_map(remote_refs, tag_refspec, &tail, 0); + else if (tags == TAGS_DEFAULT && *autotags) find_non_local_tags(transport, &ref_map, &tail); - ref_remove_duplicates(ref_map); - return ref_map; + /* Now append any refs to be updated opportunistically: */ + *tail = orefs; + for (rm = orefs; rm; rm = rm->next) { + rm->fetch_head_status = FETCH_HEAD_IGNORE; + tail = &rm->next; + } + + return ref_remove_duplicates(ref_map); } #define STORE_REF_ERROR_OTHER 1 @@ -313,7 +431,7 @@ static int update_local_ref(struct ref *ref, } if (!is_null_sha1(ref->old_sha1) && - !prefixcmp(ref->name, "refs/tags/")) { + starts_with(ref->name, "refs/tags/")) { int r; r = s_update_ref("updating tag", ref, 0); strbuf_addf(display, "%c %-*s %-*s -> %s%s", @@ -336,10 +454,10 @@ static int update_local_ref(struct ref *ref, * more likely to follow a standard layout. */ const char *name = remote_ref ? remote_ref->name : ""; - if (!prefixcmp(name, "refs/tags/")) { + if (starts_with(name, "refs/tags/")) { msg = "storing tag"; what = _("[new tag]"); - } else if (!prefixcmp(name, "refs/heads/")) { + } else if (starts_with(name, "refs/heads/")) { msg = "storing head"; what = _("[new branch]"); } else { @@ -471,15 +589,15 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, kind = ""; what = ""; } - else if (!prefixcmp(rm->name, "refs/heads/")) { + else if (starts_with(rm->name, "refs/heads/")) { kind = "branch"; what = rm->name + 11; } - else if (!prefixcmp(rm->name, "refs/tags/")) { + else if (starts_with(rm->name, "refs/tags/")) { kind = "tag"; what = rm->name + 10; } - else if (!prefixcmp(rm->name, "refs/remotes/")) { + else if (starts_with(rm->name, "refs/remotes/")) { kind = "remote-tracking branch"; what = rm->name + 13; } @@ -612,106 +730,6 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map) return result; } -static int add_existing(const char *refname, const unsigned char *sha1, - int flag, void *cbdata) -{ - struct string_list *list = (struct string_list *)cbdata; - struct string_list_item *item = string_list_insert(list, refname); - item->util = xmalloc(20); - hashcpy(item->util, sha1); - return 0; -} - -static int will_fetch(struct ref **head, const unsigned char *sha1) -{ - struct ref *rm = *head; - while (rm) { - if (!hashcmp(rm->old_sha1, sha1)) - return 1; - rm = rm->next; - } - return 0; -} - -static void find_non_local_tags(struct transport *transport, - struct ref **head, - struct ref ***tail) -{ - struct string_list existing_refs = STRING_LIST_INIT_DUP; - struct string_list remote_refs = STRING_LIST_INIT_NODUP; - const struct ref *ref; - struct string_list_item *item = NULL; - - for_each_ref(add_existing, &existing_refs); - for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { - if (prefixcmp(ref->name, "refs/tags/")) - continue; - - /* - * The peeled ref always follows the matching base - * ref, so if we see a peeled ref that we don't want - * to fetch then we can mark the ref entry in the list - * as one to ignore by setting util to NULL. - */ - if (!suffixcmp(ref->name, "^{}")) { - if (item && !has_sha1_file(ref->old_sha1) && - !will_fetch(head, ref->old_sha1) && - !has_sha1_file(item->util) && - !will_fetch(head, item->util)) - item->util = NULL; - item = NULL; - continue; - } - - /* - * If item is non-NULL here, then we previously saw a - * ref not followed by a peeled reference, so we need - * to check if it is a lightweight tag that we want to - * fetch. - */ - if (item && !has_sha1_file(item->util) && - !will_fetch(head, item->util)) - item->util = NULL; - - item = NULL; - - /* skip duplicates and refs that we already have */ - if (string_list_has_string(&remote_refs, ref->name) || - string_list_has_string(&existing_refs, ref->name)) - continue; - - item = string_list_insert(&remote_refs, ref->name); - item->util = (void *)ref->old_sha1; - } - string_list_clear(&existing_refs, 1); - - /* - * We may have a final lightweight tag that needs to be - * checked to see if it needs fetching. - */ - if (item && !has_sha1_file(item->util) && - !will_fetch(head, item->util)) - item->util = NULL; - - /* - * For all the tags in the remote_refs string list, - * add them to the list of refs to be fetched - */ - for_each_string_list_item(item, &remote_refs) { - /* Unless we have already decided to ignore this item... */ - if (item->util) - { - struct ref *rm = alloc_ref(item->string); - rm->peer_ref = alloc_ref(item->string); - hashcpy(rm->old_sha1, item->util); - **tail = rm; - *tail = &rm->next; - } - } - - string_list_clear(&remote_refs, 0); -} - static void check_not_current_branch(struct ref *ref_map) { struct branch *current_branch = branch_get(NULL); @@ -831,30 +849,16 @@ static int do_fetch(struct transport *transport, } if (prune) { /* - * If --tags was specified, pretend that the user gave us - * the canonical tags refspec + * We only prune based on refspecs specified + * explicitly (via command line or configuration); we + * don't care whether --tags was specified. */ - if (tags == TAGS_SET) { - const char *tags_str = "refs/tags/*:refs/tags/*"; - struct refspec *tags_refspec, *refspec; - - /* Copy the refspec and add the tags to it */ - refspec = xcalloc(ref_count + 1, sizeof(struct refspec)); - tags_refspec = parse_fetch_refspec(1, &tags_str); - memcpy(refspec, refs, ref_count * sizeof(struct refspec)); - memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec)); - ref_count++; - - prune_refs(refspec, ref_count, ref_map); - - ref_count--; - /* The rest of the strings belong to fetch_one */ - free_refspec(1, tags_refspec); - free(refspec); - } else if (ref_count) { + if (ref_count) { prune_refs(refs, ref_count, ref_map); } else { - prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map); + prune_refs(transport->remote->fetch, + transport->remote->fetch_refspec_nr, + ref_map); } } free_refs(ref_map); @@ -892,7 +896,7 @@ static int get_remote_group(const char *key, const char *value, void *priv) { struct remote_group_data *g = priv; - if (!prefixcmp(key, "remotes.") && + if (starts_with(key, "remotes.") && !strcmp(key + 8, g->name)) { /* split list by white space */ int space = strcspn(value, " \t\n"); @@ -930,8 +934,8 @@ static void add_options_to_argv(struct argv_array *argv) { if (dry_run) argv_array_push(argv, "--dry-run"); - if (prune > 0) - argv_array_push(argv, "--prune"); + if (prune != -1) + argv_array_push(argv, prune ? "--prune" : "--no-prune"); if (update_head_ok) argv_array_push(argv, "--update-head-ok"); if (force) @@ -1075,6 +1079,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } } + /* no need to be strict, transport_set_option() will validate it again */ + if (depth && atoi(depth) < 1) + die(_("depth %s is not a positive number"), depth); + if (recurse_submodules != RECURSE_SUBMODULES_OFF) { if (recurse_submodules_default) { int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c index 1c04070869..3906eda877 100644 --- a/builtin/fmt-merge-msg.c +++ b/builtin/fmt-merge-msg.c @@ -109,7 +109,7 @@ static int handle_line(char *line, struct merge_parents *merge_parents) if (len < 43 || line[40] != '\t') return 1; - if (!prefixcmp(line + 41, "not-for-merge")) + if (starts_with(line + 41, "not-for-merge")) return 0; if (line[41] != '\t') @@ -155,16 +155,16 @@ static int handle_line(char *line, struct merge_parents *merge_parents) if (pulling_head) { origin = src; src_data->head_status |= 1; - } else if (!prefixcmp(line, "branch ")) { + } else if (starts_with(line, "branch ")) { origin_data->is_local_branch = 1; origin = line + 7; string_list_append(&src_data->branch, origin); src_data->head_status |= 2; - } else if (!prefixcmp(line, "tag ")) { + } else if (starts_with(line, "tag ")) { origin = line; string_list_append(&src_data->tag, origin + 4); src_data->head_status |= 2; - } else if (!prefixcmp(line, "remote-tracking branch ")) { + } else if (starts_with(line, "remote-tracking branch ")) { origin = line + strlen("remote-tracking branch "); string_list_append(&src_data->r_branch, origin); src_data->head_status |= 2; @@ -605,7 +605,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out, resolve_refdup("HEAD", head_sha1, 1, NULL); if (!current_branch) die("No current branch"); - if (!prefixcmp(current_branch, "refs/heads/")) + if (starts_with(current_branch, "refs/heads/")) current_branch += 11; find_merge_parents(&merge_parents, in, head_sha1); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 875bd813d5..6551e7b39b 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -453,7 +453,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru if (name[wholen] != 0 && strcmp(name + wholen, "name") && strcmp(name + wholen, "email") && - prefixcmp(name + wholen, "date")) + !starts_with(name + wholen, "date")) continue; if (!wholine) wholine = find_wholine(who, wholen, buf, sz); @@ -465,7 +465,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru v->s = copy_name(wholine); else if (!strcmp(name + wholen, "email")) v->s = copy_email(wholine); - else if (!prefixcmp(name + wholen, "date")) + else if (starts_with(name + wholen, "date")) grab_date(wholine, v, name); } @@ -487,7 +487,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru if (deref) name++; - if (!prefixcmp(name, "creatordate")) + if (starts_with(name, "creatordate")) grab_date(wholine, v, name); else if (!strcmp(name, "creator")) v->s = copy_line(wholine); @@ -668,13 +668,13 @@ static void populate_value(struct refinfo *ref) name++; } - if (!prefixcmp(name, "refname")) + if (starts_with(name, "refname")) refname = ref->refname; - else if (!prefixcmp(name, "symref")) + else if (starts_with(name, "symref")) refname = ref->symref ? ref->symref : ""; - else if (!prefixcmp(name, "upstream")) { + else if (starts_with(name, "upstream")) { /* only local branches may have an upstream */ - if (prefixcmp(ref->refname, "refs/heads/")) + if (!starts_with(ref->refname, "refs/heads/")) continue; branch = branch_get(ref->refname + 11); @@ -682,7 +682,7 @@ static void populate_value(struct refinfo *ref) !branch->merge[0]->dst) continue; refname = branch->merge[0]->dst; - } else if (!prefixcmp(name, "color:")) { + } else if (starts_with(name, "color:")) { char color[COLOR_MAXLEN] = ""; color_parse(name + 6, "--format", color); @@ -725,7 +725,7 @@ static void populate_value(struct refinfo *ref) refname = shorten_unambiguous_ref(refname, warn_ambiguous_refs); else if (!strcmp(formatp, "track") && - !prefixcmp(name, "upstream")) { + starts_with(name, "upstream")) { char buf[40]; stat_tracking_info(branch, &num_ours, &num_theirs); @@ -744,7 +744,7 @@ static void populate_value(struct refinfo *ref) } continue; } else if (!strcmp(formatp, "trackshort") && - !prefixcmp(name, "upstream")) { + starts_with(name, "upstream")) { assert(branch); stat_tracking_info(branch, &num_ours, &num_theirs); if (!num_ours && !num_theirs) diff --git a/builtin/fsck.c b/builtin/fsck.c index 97ce678c6b..1affdd5e92 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -442,7 +442,7 @@ static void fsck_dir(int i, char *path) add_sha1_list(sha1, DIRENT_SORT_HINT(de)); continue; } - if (!prefixcmp(de->d_name, "tmp_obj_")) + if (starts_with(de->d_name, "tmp_obj_")) continue; fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name); } @@ -484,7 +484,7 @@ static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, in static int is_branch(const char *refname) { - return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/"); + return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/"); } static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) @@ -566,7 +566,7 @@ static int fsck_head_link(void) if (!strcmp(head_points_at, "HEAD")) /* detached HEAD */ null_is_error = 1; - else if (prefixcmp(head_points_at, "refs/heads/")) + else if (!starts_with(head_points_at, "refs/heads/")) return error("HEAD points to something strange (%s)", head_points_at); if (is_null_sha1(head_sha1)) { diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c new file mode 100644 index 0000000000..aa72596083 --- /dev/null +++ b/builtin/get-tar-commit-id.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005, 2006 Rene Scharfe + */ +#include "cache.h" +#include "commit.h" +#include "tar.h" +#include "builtin.h" +#include "quote.h" + +static const char builtin_get_tar_commit_id_usage[] = +"git get-tar-commit-id < <tarfile>"; + +/* ustar header + extended global header content */ +#define RECORDSIZE (512) +#define HEADERSIZE (2 * RECORDSIZE) + +int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix) +{ + char buffer[HEADERSIZE]; + struct ustar_header *header = (struct ustar_header *)buffer; + char *content = buffer + RECORDSIZE; + ssize_t n; + + if (argc != 1) + usage(builtin_get_tar_commit_id_usage); + + n = read_in_full(0, buffer, HEADERSIZE); + if (n < HEADERSIZE) + die("git get-tar-commit-id: read error"); + if (header->typeflag[0] != 'g') + return 1; + if (memcmp(content, "52 comment=", 11)) + return 1; + + n = write_in_full(1, content + 11, 41); + if (n < 41) + die_errno("git get-tar-commit-id: write error"); + + return 0; +} diff --git a/builtin/help.c b/builtin/help.c index f1e236b912..cc17e670ce 100644 --- a/builtin/help.c +++ b/builtin/help.c @@ -100,7 +100,7 @@ static int check_emacsclient_version(void) */ finish_command(&ec_process); - if (prefixcmp(buffer.buf, "emacsclient")) { + if (!starts_with(buffer.buf, "emacsclient")) { strbuf_release(&buffer); return error(_("Failed to parse emacsclient version.")); } @@ -258,7 +258,7 @@ static int add_man_viewer_info(const char *var, const char *value) static int git_help_config(const char *var, const char *value, void *cb) { - if (!prefixcmp(var, "column.")) + if (starts_with(var, "column.")) return git_column_config(var, value, "help", &colopts); if (!strcmp(var, "help.format")) { if (!value) @@ -278,7 +278,7 @@ static int git_help_config(const char *var, const char *value, void *cb) add_man_viewer(value); return 0; } - if (!prefixcmp(var, "man.")) + if (starts_with(var, "man.")) return add_man_viewer_info(var, value); return git_default_config(var, value, cb); @@ -306,7 +306,7 @@ static const char *cmd_to_page(const char *git_cmd) { if (!git_cmd) return "git"; - else if (!prefixcmp(git_cmd, "git")) + else if (starts_with(git_cmd, "git")) return git_cmd; else if (is_git_command(git_cmd)) return prepend("git-", git_cmd); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 9e9eb4b74e..2f37a38fbc 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1534,9 +1534,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) stat_only = 1; } else if (!strcmp(arg, "--keep")) { keep_msg = ""; - } else if (!prefixcmp(arg, "--keep=")) { + } else if (starts_with(arg, "--keep=")) { keep_msg = arg + 7; - } else if (!prefixcmp(arg, "--threads=")) { + } else if (starts_with(arg, "--threads=")) { char *end; nr_threads = strtoul(arg+10, &end, 0); if (!arg[10] || *end || nr_threads < 0) @@ -1547,7 +1547,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) "ignoring %s"), arg); nr_threads = 1; #endif - } else if (!prefixcmp(arg, "--pack_header=")) { + } else if (starts_with(arg, "--pack_header=")) { struct pack_header *hdr; char *c; @@ -1566,7 +1566,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (index_name || (i+1) >= argc) usage(index_pack_usage); index_name = argv[++i]; - } else if (!prefixcmp(arg, "--index-version=")) { + } else if (starts_with(arg, "--index-version=")) { char *c; opts.version = strtoul(arg + 16, &c, 10); if (opts.version > 2) diff --git a/builtin/init-db.c b/builtin/init-db.c index 78aa3872dd..b3f03cf0d6 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -266,7 +266,7 @@ static int create_default_files(const char *template_path) /* allow template config file to override the default */ if (log_all_ref_updates == -1) git_config_set("core.logallrefupdates", "true"); - if (prefixcmp(git_dir, work_tree) || + if (!starts_with(git_dir, work_tree) || strcmp(git_dir + strlen(work_tree), "/.git")) { git_config_set("core.worktree", work_tree); } diff --git a/builtin/log.c b/builtin/log.c index b708517a35..b97373da3b 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -391,7 +391,7 @@ static int git_log_config(const char *var, const char *value, void *cb) default_show_root = git_config_bool(var, value); return 0; } - if (!prefixcmp(var, "color.decorate.")) + if (starts_with(var, "color.decorate.")) return parse_decorate_color_config(var, 15, value); if (!strcmp(var, "log.mailmap")) { use_mailmap_config = git_config_bool(var, value); @@ -477,7 +477,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev) int new_offset = offset + 1; while (new_offset < size && buf[new_offset++] != '\n') ; /* do nothing */ - if (!prefixcmp(buf + offset, "tagger ")) + if (starts_with(buf + offset, "tagger ")) show_tagger(buf + offset + 7, new_offset - offset - 7, rev); offset = new_offset; @@ -882,7 +882,7 @@ static char *find_branch_name(struct rev_info *rev) ref = rev->cmdline.rev[positive].name; tip_sha1 = rev->cmdline.rev[positive].item->sha1; if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) && - !prefixcmp(full_ref, "refs/heads/") && + starts_with(full_ref, "refs/heads/") && !hashcmp(tip_sha1, branch_sha1)) branch = xstrdup(full_ref + strlen("refs/heads/")); free(full_ref); @@ -1388,7 +1388,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) unsigned char sha1[20]; const char *ref; ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL); - if (ref && !prefixcmp(ref, "refs/heads/")) + if (ref && starts_with(ref, "refs/heads/")) branch_name = xstrdup(ref + strlen("refs/heads/")); else branch_name = xstrdup(""); /* no branch */ diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c index 25e83cfe9d..39e5144b9e 100644 --- a/builtin/ls-remote.c +++ b/builtin/ls-remote.c @@ -50,11 +50,11 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) const char *arg = argv[i]; if (*arg == '-') { - if (!prefixcmp(arg, "--upload-pack=")) { + if (starts_with(arg, "--upload-pack=")) { uploadpack = arg + 14; continue; } - if (!prefixcmp(arg, "--exec=")) { + if (starts_with(arg, "--exec=")) { uploadpack = arg + 7; continue; } diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c index 24a772d8e1..2c3cd8eab7 100644 --- a/builtin/mailinfo.c +++ b/builtin/mailinfo.c @@ -328,11 +328,11 @@ static int check_header(const struct strbuf *line, } /* for inbody stuff */ - if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5])) { + if (starts_with(line->buf, ">From") && isspace(line->buf[5])) { ret = 1; /* Should this return 0? */ goto check_header_out; } - if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) { + if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) { for (i = 0; header[i]; i++) { if (!memcmp("Subject", header[i], 7)) { handle_header(&hdr_data[i], line); @@ -361,7 +361,7 @@ static int is_rfc2822_header(const struct strbuf *line) char *cp = line->buf; /* Count mbox From headers as headers */ - if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From ")) + if (starts_with(cp, "From ") || starts_with(cp, ">From ")) return 1; while ((ch = *cp++)) { @@ -671,11 +671,11 @@ static inline int patchbreak(const struct strbuf *line) size_t i; /* Beginning of a "diff -" header? */ - if (!prefixcmp(line->buf, "diff -")) + if (starts_with(line->buf, "diff -")) return 1; /* CVS "Index: " line? */ - if (!prefixcmp(line->buf, "Index: ")) + if (starts_with(line->buf, "Index: ")) return 1; /* @@ -685,7 +685,7 @@ static inline int patchbreak(const struct strbuf *line) if (line->len < 4) return 0; - if (!prefixcmp(line->buf, "---")) { + if (starts_with(line->buf, "---")) { /* space followed by a filename? */ if (line->buf[3] == ' ' && !isspace(line->buf[4])) return 1; @@ -986,7 +986,7 @@ static int mailinfo(FILE *in, FILE *out, const char *msg, const char *patch) static int git_mailinfo_config(const char *var, const char *value, void *unused) { - if (prefixcmp(var, "mailinfo.")) + if (!starts_with(var, "mailinfo.")) return git_default_config(var, value, unused); if (!strcmp(var, "mailinfo.scissors")) { use_scissors = git_config_bool(var, value); @@ -1020,7 +1020,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) metainfo_charset = def_charset; else if (!strcmp(argv[1], "-n")) metainfo_charset = NULL; - else if (!prefixcmp(argv[1], "--encoding=")) + else if (starts_with(argv[1], "--encoding=")) metainfo_charset = argv[1] + 11; else if (!strcmp(argv[1], "--scissors")) use_scissors = 1; diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index 3a64f5d0bd..a90f28f34d 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -29,7 +29,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) struct commit *result; init_merge_options(&o); - if (argv[0] && !suffixcmp(argv[0], "-subtree")) + if (argv[0] && ends_with(argv[0], "-subtree")) o.subtree_shift = ""; if (argc < 4) @@ -38,7 +38,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; ++i) { const char *arg = argv[i]; - if (!prefixcmp(arg, "--")) { + if (starts_with(arg, "--")) { if (!arg[2]) break; if (parse_merge_opt(&o, arg + 2)) diff --git a/builtin/merge.c b/builtin/merge.c index 41fb66dec2..4941a6c36a 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -446,17 +446,17 @@ static void merge_name(const char *remote, struct strbuf *msg) die(_("'%s' does not point to a commit"), remote); if (dwim_ref(remote, strlen(remote), branch_head, &found_ref) > 0) { - if (!prefixcmp(found_ref, "refs/heads/")) { + if (starts_with(found_ref, "refs/heads/")) { strbuf_addf(msg, "%s\t\tbranch '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; } - if (!prefixcmp(found_ref, "refs/tags/")) { + if (starts_with(found_ref, "refs/tags/")) { strbuf_addf(msg, "%s\t\ttag '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; } - if (!prefixcmp(found_ref, "refs/remotes/")) { + if (starts_with(found_ref, "refs/remotes/")) { strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n", sha1_to_hex(branch_head), remote); goto cleanup; @@ -570,8 +570,8 @@ static int git_merge_config(const char *k, const char *v, void *cb) { int status; - if (branch && !prefixcmp(k, "branch.") && - !prefixcmp(k + 7, branch) && + if (branch && starts_with(k, "branch.") && + starts_with(k + 7, branch) && !strcmp(k + 7 + strlen(branch), ".mergeoptions")) { free(branch_mergeoptions); branch_mergeoptions = xstrdup(v); @@ -1106,7 +1106,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * current branch. */ branch = branch_to_free = resolve_refdup("HEAD", head_sha1, 0, &flag); - if (branch && !prefixcmp(branch, "refs/heads/")) + if (branch && starts_with(branch, "refs/heads/")) branch += 11; if (!branch || is_null_sha1(head_sha1)) head_commit = NULL; diff --git a/builtin/mv.c b/builtin/mv.c index 2e0e61b651..08fbc033e4 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -16,9 +16,12 @@ static const char * const builtin_mv_usage[] = { NULL }; +#define DUP_BASENAME 1 +#define KEEP_TRAILING_SLASH 2 + static const char **internal_copy_pathspec(const char *prefix, const char **pathspec, - int count, int base_name) + int count, unsigned flags) { int i; const char **result = xmalloc((count + 1) * sizeof(const char *)); @@ -27,11 +30,12 @@ static const char **internal_copy_pathspec(const char *prefix, for (i = 0; i < count; i++) { int length = strlen(result[i]); int to_copy = length; - while (to_copy > 0 && is_dir_sep(result[i][to_copy - 1])) + while (!(flags & KEEP_TRAILING_SLASH) && + to_copy > 0 && is_dir_sep(result[i][to_copy - 1])) to_copy--; - if (to_copy != length || base_name) { + if (to_copy != length || flags & DUP_BASENAME) { char *it = xmemdupz(result[i], to_copy); - if (base_name) { + if (flags & DUP_BASENAME) { result[i] = xstrdup(basename(it)); free(it); } else @@ -87,16 +91,21 @@ int cmd_mv(int argc, const char **argv, const char *prefix) source = internal_copy_pathspec(prefix, argv, argc, 0); modes = xcalloc(argc, sizeof(enum update_mode)); - dest_path = internal_copy_pathspec(prefix, argv + argc, 1, 0); + /* + * Keep trailing slash, needed to let + * "git mv file no-such-dir/" error out. + */ + dest_path = internal_copy_pathspec(prefix, argv + argc, 1, + KEEP_TRAILING_SLASH); submodule_gitfile = xcalloc(argc, sizeof(char *)); if (dest_path[0][0] == '\0') /* special case: "." was normalized to "" */ - destination = internal_copy_pathspec(dest_path[0], argv, argc, 1); + destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME); else if (!lstat(dest_path[0], &st) && S_ISDIR(st.st_mode)) { dest_path[0] = add_slash(dest_path[0]); - destination = internal_copy_pathspec(dest_path[0], argv, argc, 1); + destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME); } else { if (argc != 1) die("destination '%s' is not a directory", dest_path[0]); diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 23daaa7d99..0b21d7e5b2 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -100,9 +100,9 @@ static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous) { if (shorten_unambiguous) refname = shorten_unambiguous_ref(refname, 0); - else if (!prefixcmp(refname, "refs/heads/")) + else if (starts_with(refname, "refs/heads/")) refname = refname + 11; - else if (!prefixcmp(refname, "refs/")) + else if (starts_with(refname, "refs/")) refname = refname + 5; return refname; } @@ -148,7 +148,7 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void int can_abbreviate_output = data->tags_only && data->name_only; int deref = 0; - if (data->tags_only && prefixcmp(path, "refs/tags/")) + if (data->tags_only && !starts_with(path, "refs/tags/")) return 0; if (data->ref_filter) { diff --git a/builtin/notes.c b/builtin/notes.c index d459e23c42..2b24d059b5 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -347,7 +347,7 @@ static struct notes_tree *init_notes_check(const char *subcommand) init_notes(NULL, NULL, NULL, 0); t = &default_notes_tree; - if (prefixcmp(t->ref, "refs/notes/")) + if (!starts_with(t->ref, "refs/notes/")) die("Refusing to %s notes in %s (outside of refs/notes/)", subcommand, t->ref); return t; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 36273dd6f0..dfb4d84caa 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -2032,7 +2032,7 @@ static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, vo { unsigned char peeled[20]; - if (!prefixcmp(path, "refs/tags/") && /* is a tag? */ + if (starts_with(path, "refs/tags/") && /* is a tag? */ !peel_ref(path, peeled) && /* peelable? */ locate_object_entry(peeled)) /* object packed? */ add_object_entry(sha1, OBJ_TAG, NULL, 0); diff --git a/builtin/prune.c b/builtin/prune.c index 6366917c6d..a85ef54d5a 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -80,7 +80,7 @@ static int prune_dir(int i, char *path) prune_object(path, de->d_name, sha1); continue; } - if (!prefixcmp(de->d_name, "tmp_obj_")) { + if (starts_with(de->d_name, "tmp_obj_")) { prune_tmp_object(path, de->d_name); continue; } @@ -119,7 +119,7 @@ static void remove_temporary_files(const char *path) return; } while ((de = readdir(dir)) != NULL) - if (!prefixcmp(de->d_name, "tmp_")) + if (starts_with(de->d_name, "tmp_")) prune_tmp_object(path, de->d_name); closedir(dir); } diff --git a/builtin/push.c b/builtin/push.c index a73982a308..0e50ddbb01 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -35,35 +35,75 @@ static void add_refspec(const char *ref) refspec[refspec_nr-1] = ref; } -static void set_refspecs(const char **refs, int nr) +static const char *map_refspec(const char *ref, + struct remote *remote, struct ref *local_refs) { + struct ref *matched = NULL; + + /* Does "ref" uniquely name our ref? */ + if (count_refspec_match(ref, local_refs, &matched) != 1) + return ref; + + if (remote->push) { + struct refspec query; + memset(&query, 0, sizeof(struct refspec)); + query.src = matched->name; + if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) && + query.dst) { + struct strbuf buf = STRBUF_INIT; + strbuf_addf(&buf, "%s%s:%s", + query.force ? "+" : "", + query.src, query.dst); + return strbuf_detach(&buf, NULL); + } + } + + if (push_default == PUSH_DEFAULT_UPSTREAM && + !prefixcmp(matched->name, "refs/heads/")) { + struct branch *branch = branch_get(matched->name + 11); + if (branch->merge_nr == 1 && branch->merge[0]->src) { + struct strbuf buf = STRBUF_INIT; + strbuf_addf(&buf, "%s:%s", + ref, branch->merge[0]->src); + return strbuf_detach(&buf, NULL); + } + } + + return ref; +} + +static void set_refspecs(const char **refs, int nr, const char *repo) +{ + struct remote *remote = NULL; + struct ref *local_refs = NULL; int i; + for (i = 0; i < nr; i++) { const char *ref = refs[i]; if (!strcmp("tag", ref)) { - char *tag; - int len; + struct strbuf tagref = STRBUF_INIT; if (nr <= ++i) die(_("tag shorthand without <tag>")); - len = strlen(refs[i]) + 11; - if (deleterefs) { - tag = xmalloc(len+1); - strcpy(tag, ":refs/tags/"); - } else { - tag = xmalloc(len); - strcpy(tag, "refs/tags/"); + ref = refs[i]; + if (deleterefs) + strbuf_addf(&tagref, ":refs/tags/%s", ref); + else + strbuf_addf(&tagref, "refs/tags/%s", ref); + ref = strbuf_detach(&tagref, NULL); + } else if (deleterefs) { + struct strbuf delref = STRBUF_INIT; + if (strchr(ref, ':')) + die(_("--delete only accepts plain target ref names")); + strbuf_addf(&delref, ":%s", ref); + ref = strbuf_detach(&delref, NULL); + } else if (!strchr(ref, ':')) { + if (!remote) { + /* lazily grab remote and local_refs */ + remote = remote_get(repo); + local_refs = get_local_heads(); } - strcat(tag, refs[i]); - ref = tag; - } else if (deleterefs && !strchr(ref, ':')) { - char *delref; - int len = strlen(ref)+1; - delref = xmalloc(len+1); - strcpy(delref, ":"); - strcat(delref, ref); - ref = delref; - } else if (deleterefs) - die(_("--delete only accepts plain target ref names")); + ref = map_refspec(ref, remote, local_refs); + } add_refspec(ref); } } @@ -501,7 +541,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) if (argc > 0) { repo = argv[0]; - set_refspecs(argv + 1, argc - 1); + set_refspecs(argv + 1, argc - 1, repo); } rc = do_push(repo, flags); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 67ce1ef105..e09994f4df 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -428,7 +428,7 @@ static const char *update(struct command *cmd) struct ref_lock *lock; /* only refs/... are allowed */ - if (prefixcmp(name, "refs/") || check_refname_format(name + 5, 0)) { + if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) { rp_error("refusing to create funny ref '%s' remotely", name); return "funny refname"; } @@ -459,7 +459,7 @@ static const char *update(struct command *cmd) } if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) { - if (deny_deletes && !prefixcmp(name, "refs/heads/")) { + if (deny_deletes && starts_with(name, "refs/heads/")) { rp_error("denying ref deletion for %s", name); return "deletion prohibited"; } @@ -483,7 +483,7 @@ static const char *update(struct command *cmd) if (deny_non_fast_forwards && !is_null_sha1(new_sha1) && !is_null_sha1(old_sha1) && - !prefixcmp(name, "refs/heads/")) { + starts_with(name, "refs/heads/")) { struct object *old_object, *new_object; struct commit *old_commit, *new_commit; diff --git a/builtin/reflog.c b/builtin/reflog.c index 6eb24c8da2..852cff60b7 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -610,12 +610,12 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) const char *arg = argv[i]; if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) cb.dry_run = 1; - else if (!prefixcmp(arg, "--expire=")) { + else if (starts_with(arg, "--expire=")) { if (parse_expiry_date(arg + 9, &cb.expire_total)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_TOTAL; } - else if (!prefixcmp(arg, "--expire-unreachable=")) { + else if (starts_with(arg, "--expire-unreachable=")) { if (parse_expiry_date(arg + 21, &cb.expire_unreachable)) die(_("'%s' is not a valid timestamp"), arg); explicit_expiry |= EXPIRE_UNREACH; diff --git a/builtin/remote.c b/builtin/remote.c index 4e14891095..b3ab4cf8f6 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -6,6 +6,7 @@ #include "strbuf.h" #include "run-command.h" #include "refs.h" +#include "argv-array.h" static const char * const builtin_remote_usage[] = { N_("git remote [-v | --verbose]"), @@ -77,17 +78,6 @@ static const char * const builtin_remote_seturl_usage[] = { static int verbose; -static int show_all(void); -static int prune_remote(const char *remote, int dry_run); - -static inline int postfixcmp(const char *string, const char *postfix) -{ - int len1 = strlen(string), len2 = strlen(postfix); - if (len1 < len2) - return 1; - return strcmp(string + len1 - len2, postfix); -} - static int fetch_remote(const char *name) { const char *argv[] = { "fetch", name, NULL, NULL }; @@ -269,7 +259,7 @@ static const char *abbrev_ref(const char *name, const char *prefix) static int config_read_branches(const char *key, const char *value, void *cb) { - if (!prefixcmp(key, "branch.")) { + if (starts_with(key, "branch.")) { const char *orig_key = key; char *name; struct string_list_item *item; @@ -277,13 +267,13 @@ static int config_read_branches(const char *key, const char *value, void *cb) enum { REMOTE, MERGE, REBASE } type; key += 7; - if (!postfixcmp(key, ".remote")) { + if (ends_with(key, ".remote")) { name = xstrndup(key, strlen(key) - 7); type = REMOTE; - } else if (!postfixcmp(key, ".merge")) { + } else if (ends_with(key, ".merge")) { name = xstrndup(key, strlen(key) - 6); type = MERGE; - } else if (!postfixcmp(key, ".rebase")) { + } else if (ends_with(key, ".rebase")) { name = xstrndup(key, strlen(key) - 7); type = REBASE; } else @@ -309,8 +299,13 @@ static int config_read_branches(const char *key, const char *value, void *cb) space = strchr(value, ' '); } string_list_append(&info->merge, xstrdup(value)); - } else - info->rebase = git_config_bool(orig_key, value); + } else { + int v = git_config_maybe_bool(orig_key, value); + if (v >= 0) + info->rebase = v; + else if (!strcmp(value, "preserve")) + info->rebase = 1; + } } return 0; } @@ -534,9 +529,9 @@ static int add_branch_for_removal(const char *refname, } /* don't delete non-remote-tracking refs */ - if (prefixcmp(refname, "refs/remotes/")) { + if (!starts_with(refname, "refs/remotes/")) { /* advise user how to delete local branches */ - if (!prefixcmp(refname, "refs/heads/")) + if (starts_with(refname, "refs/heads/")) string_list_append(branches->skipped, abbrev_branch(refname)); /* silently skip over other non-remote refs */ @@ -571,7 +566,7 @@ static int read_remote_branches(const char *refname, const char *symref; strbuf_addf(&buf, "refs/remotes/%s/", rename->old); - if (!prefixcmp(refname, buf.buf)) { + if (starts_with(refname, buf.buf)) { item = string_list_append(rename->remote_branches, xstrdup(refname)); symref = resolve_ref_unsafe(refname, orig_sha1, 1, &flag); if (flag & REF_ISSYMREF) @@ -1084,6 +1079,64 @@ static int show_push_info_item(struct string_list_item *item, void *cb_data) return 0; } +static int get_one_entry(struct remote *remote, void *priv) +{ + struct string_list *list = priv; + struct strbuf url_buf = STRBUF_INIT; + const char **url; + int i, url_nr; + + if (remote->url_nr > 0) { + strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]); + string_list_append(list, remote->name)->util = + strbuf_detach(&url_buf, NULL); + } else + string_list_append(list, remote->name)->util = NULL; + if (remote->pushurl_nr) { + url = remote->pushurl; + url_nr = remote->pushurl_nr; + } else { + url = remote->url; + url_nr = remote->url_nr; + } + for (i = 0; i < url_nr; i++) + { + strbuf_addf(&url_buf, "%s (push)", url[i]); + string_list_append(list, remote->name)->util = + strbuf_detach(&url_buf, NULL); + } + + return 0; +} + +static int show_all(void) +{ + struct string_list list = STRING_LIST_INIT_NODUP; + int result; + + list.strdup_strings = 1; + result = for_each_remote(get_one_entry, &list); + + if (!result) { + int i; + + sort_string_list(&list); + for (i = 0; i < list.nr; i++) { + struct string_list_item *item = list.items + i; + if (verbose) + printf("%s\t%s\n", item->string, + item->util ? (const char *)item->util : ""); + else { + if (i && !strcmp((item - 1)->string, item->string)) + continue; + printf("%s\n", item->string); + } + } + } + string_list_clear(&list, 1); + return result; +} + static int show(int argc, const char **argv) { int no_query = 0, result = 0, query_flag = 0; @@ -1246,26 +1299,6 @@ static int set_head(int argc, const char **argv) return result; } -static int prune(int argc, const char **argv) -{ - int dry_run = 0, result = 0; - struct option options[] = { - OPT__DRY_RUN(&dry_run, N_("dry run")), - OPT_END() - }; - - argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage, - 0); - - if (argc < 1) - usage_with_options(builtin_remote_prune_usage, options); - - for (; argc; argc--, argv++) - result |= prune_remote(*argv, dry_run); - - return result; -} - static int prune_remote(const char *remote, int dry_run) { int result = 0, i; @@ -1304,6 +1337,26 @@ static int prune_remote(const char *remote, int dry_run) return result; } +static int prune(int argc, const char **argv) +{ + int dry_run = 0, result = 0; + struct option options[] = { + OPT__DRY_RUN(&dry_run, N_("dry run")), + OPT_END() + }; + + argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage, + 0); + + if (argc < 1) + usage_with_options(builtin_remote_prune_usage, options); + + for (; argc; argc--, argv++) + result |= prune_remote(*argv, dry_run); + + return result; +} + static int get_remote_default(const char *key, const char *value, void *priv) { if (strcmp(key, "remotes.default") == 0) { @@ -1315,42 +1368,42 @@ static int get_remote_default(const char *key, const char *value, void *priv) static int update(int argc, const char **argv) { - int i, prune = 0; + int i, prune = -1; struct option options[] = { OPT_BOOL('p', "prune", &prune, N_("prune remotes after fetching")), OPT_END() }; - const char **fetch_argv; - int fetch_argc = 0; + struct argv_array fetch_argv = ARGV_ARRAY_INIT; int default_defined = 0; - - fetch_argv = xmalloc(sizeof(char *) * (argc+5)); + int retval; argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage, PARSE_OPT_KEEP_ARGV0); - fetch_argv[fetch_argc++] = "fetch"; + argv_array_push(&fetch_argv, "fetch"); - if (prune) - fetch_argv[fetch_argc++] = "--prune"; + if (prune != -1) + argv_array_push(&fetch_argv, prune ? "--prune" : "--no-prune"); if (verbose) - fetch_argv[fetch_argc++] = "-v"; - fetch_argv[fetch_argc++] = "--multiple"; + argv_array_push(&fetch_argv, "-v"); + argv_array_push(&fetch_argv, "--multiple"); if (argc < 2) - fetch_argv[fetch_argc++] = "default"; + argv_array_push(&fetch_argv, "default"); for (i = 1; i < argc; i++) - fetch_argv[fetch_argc++] = argv[i]; + argv_array_push(&fetch_argv, argv[i]); - if (strcmp(fetch_argv[fetch_argc-1], "default") == 0) { + if (strcmp(fetch_argv.argv[fetch_argv.argc-1], "default") == 0) { git_config(get_remote_default, &default_defined); - if (!default_defined) - fetch_argv[fetch_argc-1] = "--all"; + if (!default_defined) { + argv_array_pop(&fetch_argv); + argv_array_push(&fetch_argv, "--all"); + } } - fetch_argv[fetch_argc] = NULL; - - return run_command_v_opt(fetch_argv, RUN_GIT_CMD); + retval = run_command_v_opt(fetch_argv.argv, RUN_GIT_CMD); + argv_array_clear(&fetch_argv); + return retval; } static int remove_all_fetch_refspecs(const char *remote, const char *key) @@ -1505,64 +1558,6 @@ static int set_url(int argc, const char **argv) return 0; } -static int get_one_entry(struct remote *remote, void *priv) -{ - struct string_list *list = priv; - struct strbuf url_buf = STRBUF_INIT; - const char **url; - int i, url_nr; - - if (remote->url_nr > 0) { - strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]); - string_list_append(list, remote->name)->util = - strbuf_detach(&url_buf, NULL); - } else - string_list_append(list, remote->name)->util = NULL; - if (remote->pushurl_nr) { - url = remote->pushurl; - url_nr = remote->pushurl_nr; - } else { - url = remote->url; - url_nr = remote->url_nr; - } - for (i = 0; i < url_nr; i++) - { - strbuf_addf(&url_buf, "%s (push)", url[i]); - string_list_append(list, remote->name)->util = - strbuf_detach(&url_buf, NULL); - } - - return 0; -} - -static int show_all(void) -{ - struct string_list list = STRING_LIST_INIT_NODUP; - int result; - - list.strdup_strings = 1; - result = for_each_remote(get_one_entry, &list); - - if (!result) { - int i; - - sort_string_list(&list); - for (i = 0; i < list.nr; i++) { - struct string_list_item *item = list.items + i; - if (verbose) - printf("%s\t%s\n", item->string, - item->util ? (const char *)item->util : ""); - else { - if (i && !strcmp((item - 1)->string, item->string)) - continue; - printf("%s\n", item->string); - } - } - } - string_list_clear(&list, 1); - return result; -} - int cmd_remote(int argc, const char **argv, const char *prefix) { struct option options[] = { diff --git a/builtin/repack.c b/builtin/repack.c index a0ff5c704f..ba66c6e377 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -78,7 +78,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list) return; while ((e = readdir(dir)) != NULL) { - if (suffixcmp(e->d_name, ".pack")) + if (!ends_with(e->d_name, ".pack")) continue; len = strlen(e->d_name) - strlen(".pack"); @@ -123,7 +123,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) struct string_list rollback = STRING_LIST_INIT_NODUP; struct string_list existing_packs = STRING_LIST_INIT_DUP; struct strbuf line = STRBUF_INIT; - int nr_packs, ext, ret, failed; + int ext, ret, failed; FILE *out; /* variables to be filled by option parsing */ @@ -233,13 +233,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix) if (ret) return ret; - nr_packs = 0; out = xfdopen(cmd.out, "r"); while (strbuf_getline(&line, out, '\n') != EOF) { if (line.len != 40) die("repack: Expecting 40 character sha1 lines only from pack-objects."); string_list_append(&names, line.buf); - nr_packs++; } fclose(out); ret = finish_command(&cmd); @@ -247,7 +245,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) return ret; argv_array_clear(&cmd_args); - if (!nr_packs && !quiet) + if (!names.nr && !quiet) printf("Nothing new to pack.\n"); /* diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 1d9ecafd41..aaeb611a97 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -286,6 +286,7 @@ static int try_difference(const char *arg) exclude = n; } } + *dotdot = '.'; return 1; } *dotdot = '.'; @@ -309,8 +310,10 @@ static int try_parent_shorthands(const char *arg) return 0; *dotdot = 0; - if (get_sha1_committish(arg, sha1)) + if (get_sha1_committish(arg, sha1)) { + *dotdot = '^'; return 0; + } if (!parents_only) show_rev(NORMAL, sha1, arg); @@ -319,6 +322,7 @@ static int try_parent_shorthands(const char *arg) show_rev(parents_only ? NORMAL : REVERSED, parents->item->object.sha1, arg); + *dotdot = '^'; return 1; } @@ -488,6 +492,7 @@ N_("git rev-parse --parseopt [options] -- [<args>...]\n" int cmd_rev_parse(int argc, const char **argv, const char *prefix) { int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0; + int has_dashdash = 0; int output_prefix = 0; unsigned char sha1[20]; const char *name = NULL; @@ -501,6 +506,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) if (argc > 1 && !strcmp("-h", argv[1])) usage(builtin_rev_parse_usage); + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "--")) { + has_dashdash = 1; + break; + } + } + prefix = setup_git_directory(); git_config(git_default_config, NULL); for (i = 1; i < argc; i++) { @@ -520,7 +532,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } continue; } - if (!prefixcmp(arg, "-n")) { + if (starts_with(arg, "-n")) { if ((filter & DO_FLAGS) && (filter & DO_REVS)) show(arg); continue; @@ -572,7 +584,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--short") || - !prefixcmp(arg, "--short=")) { + starts_with(arg, "--short=")) { filter &= ~(DO_FLAGS|DO_NOREV); verify = 1; abbrev = DEFAULT_ABBREV; @@ -600,7 +612,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) symbolic = SHOW_SYMBOLIC_FULL; continue; } - if (!prefixcmp(arg, "--abbrev-ref") && + if (starts_with(arg, "--abbrev-ref") && (!arg[12] || arg[12] == '=')) { abbrev_ref = 1; abbrev_ref_strict = warn_ambiguous_refs; @@ -618,7 +630,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) for_each_ref(show_reference, NULL); continue; } - if (!prefixcmp(arg, "--disambiguate=")) { + if (starts_with(arg, "--disambiguate=")) { for_each_abbrev(arg + 15, show_abbrev, NULL); continue; } @@ -627,7 +639,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) for_each_ref_in("refs/bisect/good", anti_reference, NULL); continue; } - if (!prefixcmp(arg, "--branches=")) { + if (starts_with(arg, "--branches=")) { for_each_glob_ref_in(show_reference, arg + 11, "refs/heads/", NULL); clear_ref_exclusion(&ref_excludes); @@ -638,7 +650,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) clear_ref_exclusion(&ref_excludes); continue; } - if (!prefixcmp(arg, "--tags=")) { + if (starts_with(arg, "--tags=")) { for_each_glob_ref_in(show_reference, arg + 7, "refs/tags/", NULL); clear_ref_exclusion(&ref_excludes); @@ -649,12 +661,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) clear_ref_exclusion(&ref_excludes); continue; } - if (!prefixcmp(arg, "--glob=")) { + if (starts_with(arg, "--glob=")) { for_each_glob_ref(show_reference, arg + 7, NULL); clear_ref_exclusion(&ref_excludes); continue; } - if (!prefixcmp(arg, "--remotes=")) { + if (starts_with(arg, "--remotes=")) { for_each_glob_ref_in(show_reference, arg + 10, "refs/remotes/", NULL); clear_ref_exclusion(&ref_excludes); @@ -665,7 +677,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) clear_ref_exclusion(&ref_excludes); continue; } - if (!prefixcmp(arg, "--exclude=")) { + if (starts_with(arg, "--exclude=")) { add_ref_exclusion(&ref_excludes, arg + 10); continue; } @@ -747,19 +759,19 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) : "false"); continue; } - if (!prefixcmp(arg, "--since=")) { + if (starts_with(arg, "--since=")) { show_datestring("--max-age=", arg+8); continue; } - if (!prefixcmp(arg, "--after=")) { + if (starts_with(arg, "--after=")) { show_datestring("--max-age=", arg+8); continue; } - if (!prefixcmp(arg, "--before=")) { + if (starts_with(arg, "--before=")) { show_datestring("--min-age=", arg+9); continue; } - if (!prefixcmp(arg, "--until=")) { + if (starts_with(arg, "--until=")) { show_datestring("--min-age=", arg+8); continue; } @@ -788,6 +800,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) } if (verify) die_no_single_rev(quiet); + if (has_dashdash) + die("bad revision '%s'", arg); as_is = 1; if (!show_file(arg, output_prefix)) continue; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 4482f16efb..e7f0b97d31 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -115,15 +115,15 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) const char *arg = *argv; if (*arg == '-') { - if (!prefixcmp(arg, "--receive-pack=")) { + if (starts_with(arg, "--receive-pack=")) { receivepack = arg + 15; continue; } - if (!prefixcmp(arg, "--exec=")) { + if (starts_with(arg, "--exec=")) { receivepack = arg + 7; continue; } - if (!prefixcmp(arg, "--remote=")) { + if (starts_with(arg, "--remote=")) { remote_name = arg + 9; continue; } @@ -181,7 +181,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix) exit(1); continue; } - if (!prefixcmp(arg, "--" CAS_OPT_NAME "=")) { + if (starts_with(arg, "--" CAS_OPT_NAME "=")) { if (parse_push_cas_option(&cas, strchr(arg, '=') + 1, 0) < 0) exit(1); diff --git a/builtin/shortlog.c b/builtin/shortlog.c index c226f767aa..4b7e53623f 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -65,7 +65,7 @@ static void insert_one_record(struct shortlog *log, eol = strchr(oneline, '\n'); if (!eol) eol = oneline + strlen(oneline); - if (!prefixcmp(oneline, "[PATCH")) { + if (starts_with(oneline, "[PATCH")) { char *eob = strchr(oneline, ']'); if (eob && (!eol || eob < eol)) oneline = eob + 1; @@ -95,7 +95,7 @@ static void read_from_stdin(struct shortlog *log) while (fgets(author, sizeof(author), stdin) != NULL) { if (!(author[0] == 'A' || author[0] == 'a') || - prefixcmp(author + 1, "uthor: ")) + !starts_with(author + 1, "uthor: ")) continue; while (fgets(oneline, sizeof(oneline), stdin) && oneline[0] != '\n') @@ -123,7 +123,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit) else eol++; - if (!prefixcmp(buffer, "author ")) + if (starts_with(buffer, "author ")) author = buffer + 7; buffer = eol; } diff --git a/builtin/show-branch.c b/builtin/show-branch.c index 46902c3de4..d9217ce1e1 100644 --- a/builtin/show-branch.c +++ b/builtin/show-branch.c @@ -284,7 +284,7 @@ static void show_one_commit(struct commit *commit, int no_name) pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty); pretty_str = pretty.buf; } - if (!prefixcmp(pretty_str, "[PATCH] ")) + if (starts_with(pretty_str, "[PATCH] ")) pretty_str += 8; if (!no_name) { @@ -395,7 +395,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f { unsigned char tmp[20]; int ofs = 11; - if (prefixcmp(refname, "refs/heads/")) + if (!starts_with(refname, "refs/heads/")) return 0; /* If both heads/foo and tags/foo exists, get_sha1 would * get confused. @@ -409,7 +409,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int { unsigned char tmp[20]; int ofs = 13; - if (prefixcmp(refname, "refs/remotes/")) + if (!starts_with(refname, "refs/remotes/")) return 0; /* If both heads/foo and tags/foo exists, get_sha1 would * get confused. @@ -421,7 +421,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { - if (prefixcmp(refname, "refs/tags/")) + if (!starts_with(refname, "refs/tags/")) return 0; return append_ref(refname + 5, sha1, 0); } @@ -452,9 +452,9 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i return 0; if (fnmatch(match_ref_pattern, tail, 0)) return 0; - if (!prefixcmp(refname, "refs/heads/")) + if (starts_with(refname, "refs/heads/")) return append_head_ref(refname, sha1, flag, cb_data); - if (!prefixcmp(refname, "refs/tags/")) + if (starts_with(refname, "refs/tags/")) return append_tag_ref(refname, sha1, flag, cb_data); return append_ref(refname, sha1, 0); } @@ -479,11 +479,11 @@ static int rev_is_head(char *head, int headlen, char *name, if ((!head[0]) || (head_sha1 && sha1 && hashcmp(head_sha1, sha1))) return 0; - if (!prefixcmp(head, "refs/heads/")) + if (starts_with(head, "refs/heads/")) head += 11; - if (!prefixcmp(name, "refs/heads/")) + if (starts_with(name, "refs/heads/")) name += 11; - else if (!prefixcmp(name, "heads/")) + else if (starts_with(name, "heads/")) name += 6; return !strcmp(head, name); } @@ -812,7 +812,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) has_head++; } if (!has_head) { - int offset = !prefixcmp(head, "refs/heads/") ? 11 : 0; + int offset = starts_with(head, "refs/heads/") ? 11 : 0; append_one_rev(head + offset); } } diff --git a/builtin/show-ref.c b/builtin/show-ref.c index 9f3f5e370b..5ba1f30838 100644 --- a/builtin/show-ref.c +++ b/builtin/show-ref.c @@ -37,8 +37,8 @@ static int show_ref(const char *refname, const unsigned char *sha1, int flag, vo if (tags_only || heads_only) { int match; - match = heads_only && !prefixcmp(refname, "refs/heads/"); - match |= tags_only && !prefixcmp(refname, "refs/tags/"); + match = heads_only && starts_with(refname, "refs/heads/"); + match |= tags_only && starts_with(refname, "refs/tags/"); if (!match) return 0; } @@ -210,7 +210,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix) while (*pattern) { unsigned char sha1[20]; - if (!prefixcmp(*pattern, "refs/") && + if (starts_with(*pattern, "refs/") && !read_ref(*pattern, sha1)) { if (!quiet) show_one(*pattern, sha1); diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c index 71286b4fae..b6a711d319 100644 --- a/builtin/symbolic-ref.c +++ b/builtin/symbolic-ref.c @@ -65,7 +65,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) break; case 2: if (!strcmp(argv[0], "HEAD") && - prefixcmp(argv[1], "refs/")) + !starts_with(argv[1], "refs/")) die("Refusing to point HEAD outside of refs/"); create_symref(argv[0], argv[1], msg); break; diff --git a/builtin/tag.c b/builtin/tag.c index ea55f1d1bd..74d3780b77 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -259,7 +259,7 @@ static int git_tag_config(const char *var, const char *value, void *cb) int status = git_gpg_config(var, value, cb); if (status) return status; - if (!prefixcmp(var, "column.")) + if (starts_with(var, "column.")) return git_column_config(var, value, "tag", &colopts); return git_default_config(var, value, cb); } diff --git a/builtin/tar-tree.c b/builtin/tar-tree.c deleted file mode 100644 index ba3ffe69a9..0000000000 --- a/builtin/tar-tree.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2005, 2006 Rene Scharfe - */ -#include "cache.h" -#include "commit.h" -#include "tar.h" -#include "builtin.h" -#include "quote.h" - -static const char tar_tree_usage[] = -"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n" -"*** Note that this command is now deprecated; use \"git archive\" instead."; - -static const char builtin_get_tar_commit_id_usage[] = -"git get-tar-commit-id < <tarfile>"; - -int cmd_tar_tree(int argc, const char **argv, const char *prefix) -{ - /* - * "git tar-tree" is now a wrapper around "git archive --format=tar" - * - * $0 --remote=<repo> arg... ==> - * git archive --format=tar --remote=<repo> arg... - * $0 tree-ish ==> - * git archive --format=tar tree-ish - * $0 tree-ish basedir ==> - * git archive --format-tar --prefix=basedir tree-ish - */ - const char **nargv = xcalloc(sizeof(*nargv), argc + 3); - struct strbuf sb = STRBUF_INIT; - char *basedir_arg; - int nargc = 0; - - nargv[nargc++] = "archive"; - nargv[nargc++] = "--format=tar"; - - if (2 <= argc && !prefixcmp(argv[1], "--remote=")) { - nargv[nargc++] = argv[1]; - argv++; - argc--; - } - - /* - * Because it's just a compatibility wrapper, tar-tree supports only - * the old behaviour of reading attributes from the work tree. - */ - nargv[nargc++] = "--worktree-attributes"; - - switch (argc) { - default: - usage(tar_tree_usage); - break; - case 3: - /* base-path */ - basedir_arg = xmalloc(strlen(argv[2]) + 11); - sprintf(basedir_arg, "--prefix=%s/", argv[2]); - nargv[nargc++] = basedir_arg; - /* fallthru */ - case 2: - /* tree-ish */ - nargv[nargc++] = argv[1]; - } - nargv[nargc] = NULL; - - fprintf(stderr, - "*** \"git tar-tree\" is now deprecated.\n" - "*** Running \"git archive\" instead.\n***"); - sq_quote_argv(&sb, nargv, 0); - strbuf_addch(&sb, '\n'); - fputs(sb.buf, stderr); - strbuf_release(&sb); - return cmd_archive(nargc, nargv, prefix); -} - -/* ustar header + extended global header content */ -#define RECORDSIZE (512) -#define HEADERSIZE (2 * RECORDSIZE) - -int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix) -{ - char buffer[HEADERSIZE]; - struct ustar_header *header = (struct ustar_header *)buffer; - char *content = buffer + RECORDSIZE; - ssize_t n; - - if (argc != 1) - usage(builtin_get_tar_commit_id_usage); - - n = read_in_full(0, buffer, HEADERSIZE); - if (n < HEADERSIZE) - die("git get-tar-commit-id: read error"); - if (header->typeflag[0] != 'g') - return 1; - if (memcmp(content, "52 comment=", 11)) - return 1; - - n = write_in_full(1, content + 11, 41); - if (n < 41) - die_errno("git get-tar-commit-id: write error"); - - return 0; -} diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 2217d7b3ae..62ff673f68 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -523,7 +523,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) strict = 1; continue; } - if (!prefixcmp(arg, "--pack_header=")) { + if (starts_with(arg, "--pack_header=")) { struct pack_header *hdr; char *c; diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 702e90db2a..1292cfea11 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -229,15 +229,15 @@ static void update_refs_stdin(void) die("empty command in input"); else if (isspace(*cmd.buf)) die("whitespace before command: %s", cmd.buf); - else if (!prefixcmp(cmd.buf, "update ")) + else if (starts_with(cmd.buf, "update ")) parse_cmd_update(cmd.buf + 7); - else if (!prefixcmp(cmd.buf, "create ")) + else if (starts_with(cmd.buf, "create ")) parse_cmd_create(cmd.buf + 7); - else if (!prefixcmp(cmd.buf, "delete ")) + else if (starts_with(cmd.buf, "delete ")) parse_cmd_delete(cmd.buf + 7); - else if (!prefixcmp(cmd.buf, "verify ")) + else if (starts_with(cmd.buf, "verify ")) parse_cmd_verify(cmd.buf + 7); - else if (!prefixcmp(cmd.buf, "option ")) + else if (starts_with(cmd.buf, "option ")) parse_cmd_option(cmd.buf + 7); else die("unknown command: %s", cmd.buf); diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c index af2da35e7d..32ab94cd06 100644 --- a/builtin/upload-archive.c +++ b/builtin/upload-archive.c @@ -37,7 +37,7 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix) if (sent_argv.argc > MAX_ARGS) die("Too many options (>%d)", MAX_ARGS - 1); - if (prefixcmp(buf, arg_cmd)) + if (!starts_with(buf, arg_cmd)) die("'argument' token or flush expected"); argv_array_push(&sent_argv, buf + strlen(arg_cmd)); } |