diff options
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/cat-file.c | 40 | ||||
-rw-r--r-- | builtin/checkout.c | 2 | ||||
-rw-r--r-- | builtin/clone.c | 13 | ||||
-rw-r--r-- | builtin/commit.c | 18 | ||||
-rw-r--r-- | builtin/config.c | 2 | ||||
-rw-r--r-- | builtin/fast-export.c | 2 | ||||
-rw-r--r-- | builtin/fast-import.c | 12 | ||||
-rw-r--r-- | builtin/fetch.c | 42 | ||||
-rw-r--r-- | builtin/gc.c | 1 | ||||
-rw-r--r-- | builtin/grep.c | 4 | ||||
-rw-r--r-- | builtin/hash-object.c | 2 | ||||
-rw-r--r-- | builtin/index-pack.c | 12 | ||||
-rw-r--r-- | builtin/merge-recursive.c | 2 | ||||
-rw-r--r-- | builtin/merge.c | 28 | ||||
-rw-r--r-- | builtin/mktag.c | 9 | ||||
-rw-r--r-- | builtin/mktree.c | 2 | ||||
-rw-r--r-- | builtin/name-rev.c | 71 | ||||
-rw-r--r-- | builtin/notes.c | 2 | ||||
-rw-r--r-- | builtin/pack-objects.c | 11 | ||||
-rw-r--r-- | builtin/read-tree.c | 14 | ||||
-rw-r--r-- | builtin/receive-pack.c | 19 | ||||
-rw-r--r-- | builtin/reflog.c | 455 | ||||
-rw-r--r-- | builtin/remote.c | 47 | ||||
-rw-r--r-- | builtin/repack.c | 12 | ||||
-rw-r--r-- | builtin/replace.c | 4 | ||||
-rw-r--r-- | builtin/rev-list.c | 29 | ||||
-rw-r--r-- | builtin/shortlog.c | 10 | ||||
-rw-r--r-- | builtin/sparse-checkout.c | 1 | ||||
-rw-r--r-- | builtin/stash.c | 19 | ||||
-rw-r--r-- | builtin/submodule--helper.c | 248 | ||||
-rw-r--r-- | builtin/tag.c | 2 | ||||
-rw-r--r-- | builtin/unpack-objects.c | 8 |
32 files changed, 420 insertions, 723 deletions
diff --git a/builtin/cat-file.c b/builtin/cat-file.c index e75e110302..50cf38999d 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -156,7 +156,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, break; case 0: - if (type_from_string(exp_type) == OBJ_BLOB) { + { + enum object_type exp_type_id = type_from_string(exp_type); + + if (exp_type_id == OBJ_BLOB) { struct object_id blob_oid; if (oid_object_info(the_repository, &oid, NULL) == OBJ_TAG) { char *buffer = read_object_file(&oid, &type, @@ -178,10 +181,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, * fall-back to the usual case. */ } - buf = read_object_with_reference(the_repository, - &oid, exp_type, &size, NULL); + buf = read_object_with_reference(the_repository, &oid, + exp_type_id, &size, NULL); break; - + } default: die("git cat-file: unknown option: %s", exp_type); } @@ -357,6 +360,13 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d } } +static void print_default_format(struct strbuf *scratch, struct expand_data *data) +{ + strbuf_addf(scratch, "%s %s %"PRIuMAX"\n", oid_to_hex(&data->oid), + type_name(data->type), + (uintmax_t)data->size); +} + /* * If "pack" is non-NULL, then "offset" is the byte offset within the pack from * which the object may be accessed (though note that we may also rely on @@ -388,8 +398,14 @@ static void batch_object_write(const char *obj_name, } strbuf_reset(scratch); - strbuf_expand(scratch, opt->format, expand_format, data); - strbuf_addch(scratch, '\n'); + + if (!opt->format) { + print_default_format(scratch, data); + } else { + strbuf_expand(scratch, opt->format, expand_format, data); + strbuf_addch(scratch, '\n'); + } + batch_write(opt, scratch->buf, scratch->len); if (opt->batch_mode == BATCH_MODE_CONTENTS) { @@ -643,6 +659,8 @@ static void batch_objects_command(struct batch_options *opt, strbuf_release(&input); } +#define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)" + static int batch_objects(struct batch_options *opt) { struct strbuf input = STRBUF_INIT; @@ -651,9 +669,6 @@ static int batch_objects(struct batch_options *opt) int save_warning; int retval = 0; - if (!opt->format) - opt->format = "%(objectname) %(objecttype) %(objectsize)"; - /* * Expand once with our special mark_query flag, which will prime the * object_info to be handed to oid_object_info_extended for each @@ -661,12 +676,17 @@ static int batch_objects(struct batch_options *opt) */ memset(&data, 0, sizeof(data)); data.mark_query = 1; - strbuf_expand(&output, opt->format, expand_format, &data); + strbuf_expand(&output, + opt->format ? opt->format : DEFAULT_FORMAT, + expand_format, + &data); data.mark_query = 0; strbuf_release(&output); if (opt->transform_mode) data.split_on_whitespace = 1; + if (opt->format && !strcmp(opt->format, DEFAULT_FORMAT)) + opt->format = NULL; /* * If we are printing out the object, then always fill in the type, * since we will want to decide whether or not to stream. diff --git a/builtin/checkout.c b/builtin/checkout.c index 1afc0773d5..797681481d 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -303,7 +303,7 @@ static int checkout_merged(int pos, const struct checkout *state, * (it also writes the merge result to the object database even * when it may contain conflicts). */ - if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid)) + if (write_object_file(result_buf.ptr, result_buf.size, OBJ_BLOB, &oid)) die(_("Unable to add merge result for '%s'"), path); free(result_buf.ptr); ce = make_transient_cache_entry(mode, &oid, path, 2, ce_mem_pool); diff --git a/builtin/clone.c b/builtin/clone.c index 0aea177660..5231656379 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -33,6 +33,7 @@ #include "packfile.h" #include "list-objects-filter-options.h" #include "hook.h" +#include "bundle.h" /* * Overall FIXMEs: @@ -1172,6 +1173,18 @@ int cmd_clone(int argc, const char **argv, const char *prefix) warning(_("--local is ignored")); transport->cloning = 1; + if (is_bundle) { + struct bundle_header header = BUNDLE_HEADER_INIT; + int fd = read_bundle_header(path, &header); + int has_filter = header.filter.choice != LOFC_DISABLED; + + if (fd > 0) + close(fd); + bundle_header_release(&header); + if (has_filter) + die(_("cannot clone from filtered bundle")); + } + transport_set_option(transport, TRANS_OPT_KEEP, "yes"); if (reject_shallow) diff --git a/builtin/commit.c b/builtin/commit.c index 8b8bdad395..009a1de0a3 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -726,11 +726,13 @@ static int prepare_to_commit(const char *index_file, const char *prefix, int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE); int old_display_comment_prefix; int merge_contains_scissors = 0; + int invoked_hook; /* This checks and barfs if author is badly specified */ determine_author_info(author_ident); - if (!no_verify && run_commit_hook(use_editor, index_file, "pre-commit", NULL)) + if (!no_verify && run_commit_hook(use_editor, index_file, &invoked_hook, + "pre-commit", NULL)) return 0; if (squash_message) { @@ -1053,10 +1055,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - if (!no_verify && hook_exists("pre-commit")) { + if (!no_verify && invoked_hook) { /* - * Re-read the index as pre-commit hook could have updated it, - * and write it out as a tree. We must do this before we invoke + * Re-read the index as the pre-commit-commit hook was invoked + * and could have updated it. We must do this before we invoke * the editor and after we invoke run_status above. */ discard_cache(); @@ -1068,7 +1070,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix, return 0; } - if (run_commit_hook(use_editor, index_file, "prepare-commit-msg", + if (run_commit_hook(use_editor, index_file, NULL, "prepare-commit-msg", git_path_commit_editmsg(), hook_arg1, hook_arg2, NULL)) return 0; @@ -1085,7 +1087,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, } if (!no_verify && - run_commit_hook(use_editor, index_file, "commit-msg", git_path_commit_editmsg(), NULL)) { + run_commit_hook(use_editor, index_file, NULL, "commit-msg", + git_path_commit_editmsg(), NULL)) { return 0; } @@ -1841,7 +1844,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) repo_rerere(the_repository, 0); run_auto_maintenance(quiet); - run_commit_hook(use_editor, get_index_file(), "post-commit", NULL); + run_commit_hook(use_editor, get_index_file(), NULL, "post-commit", + NULL); if (amend && !no_post_rewrite) { commit_post_rewrite(the_repository, current_head, &oid); } diff --git a/builtin/config.c b/builtin/config.c index ebec61868b..e7b88a9c08 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -151,7 +151,7 @@ static struct option builtin_config_options[] = { OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR), OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL), OPT_GROUP(N_("Type")), - OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type), + OPT_CALLBACK('t', "type", &type, N_("type"), N_("value is given this type"), option_parse_type), OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL), OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT), OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT), diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 510139e9b5..a7d72697fb 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -300,7 +300,7 @@ static void export_blob(const struct object_id *oid) if (!buf) die("could not read blob %s", oid_to_hex(oid)); if (check_object_signature(the_repository, oid, buf, size, - type_name(type), NULL) < 0) + type) < 0) die("oid mismatch in blob %s", oid_to_hex(oid)); object = parse_object_buffer(the_repository, oid, type, size, buf, &eaten); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index b7105fcad9..ad045c7c2d 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -944,8 +944,8 @@ static int store_object( git_hash_ctx c; git_zstream s; - hdrlen = xsnprintf((char *)hdr, sizeof(hdr), "%s %lu", - type_name(type), (unsigned long)dat->len) + 1; + hdrlen = format_object_header((char *)hdr, sizeof(hdr), type, + dat->len); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, hdr, hdrlen); the_hash_algo->update_fn(&c, dat->buf, dat->len); @@ -1098,7 +1098,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark) hashfile_checkpoint(pack_file, &checkpoint); offset = checkpoint.offset; - hdrlen = xsnprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1; + hdrlen = format_object_header((char *)out_buf, out_sz, OBJ_BLOB, len); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, out_buf, hdrlen); @@ -2490,7 +2490,7 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa unsigned long size; char *buf = read_object_with_reference(the_repository, &commit_oid, - commit_type, &size, + OBJ_COMMIT, &size, &commit_oid); if (!buf || size < the_hash_algo->hexsz + 6) die("Not a valid commit: %s", p); @@ -2562,7 +2562,7 @@ static void parse_from_existing(struct branch *b) char *buf; buf = read_object_with_reference(the_repository, - &b->oid, commit_type, &size, + &b->oid, OBJ_COMMIT, &size, &b->oid); parse_from_commit(b, buf, size); free(buf); @@ -2658,7 +2658,7 @@ static struct hash_list *parse_merge(unsigned int *count) unsigned long size; char *buf = read_object_with_reference(the_repository, &n->oid, - commit_type, + OBJ_COMMIT, &size, &n->oid); if (!buf || size < the_hash_algo->hexsz + 6) die("Not a valid commit: %s", from); diff --git a/builtin/fetch.c b/builtin/fetch.c index e8305b6662..4d12c2fd4d 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -1146,7 +1146,6 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, want_status <= FETCH_HEAD_IGNORE; want_status++) { for (rm = ref_map; rm; rm = rm->next) { - struct commit *commit = NULL; struct ref *ref = NULL; if (rm->status == REF_STATUS_REJECT_SHALLOW) { @@ -1157,21 +1156,34 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, } /* - * References in "refs/tags/" are often going to point - * to annotated tags, which are not part of the - * commit-graph. We thus only try to look up refs in - * the graph which are not in that namespace to not - * regress performance in repositories with many - * annotated tags. + * When writing FETCH_HEAD we need to determine whether + * we already have the commit or not. If not, then the + * reference is not for merge and needs to be written + * to the reflog after other commits which we already + * have. We're not interested in this property though + * in case FETCH_HEAD is not to be updated, so we can + * skip the classification in that case. */ - if (!starts_with(rm->name, "refs/tags/")) - commit = lookup_commit_in_graph(the_repository, &rm->old_oid); - if (!commit) { - commit = lookup_commit_reference_gently(the_repository, - &rm->old_oid, - 1); - if (!commit) - rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE; + if (fetch_head->fp) { + struct commit *commit = NULL; + + /* + * References in "refs/tags/" are often going to point + * to annotated tags, which are not part of the + * commit-graph. We thus only try to look up refs in + * the graph which are not in that namespace to not + * regress performance in repositories with many + * annotated tags. + */ + if (!starts_with(rm->name, "refs/tags/")) + commit = lookup_commit_in_graph(the_repository, &rm->old_oid); + if (!commit) { + commit = lookup_commit_reference_gently(the_repository, + &rm->old_oid, + 1); + if (!commit) + rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE; + } } if (rm->fetch_head_status != want_status) diff --git a/builtin/gc.c b/builtin/gc.c index ffaf0daf5d..b335cffa33 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -30,7 +30,6 @@ #include "promisor-remote.h" #include "refs.h" #include "remote.h" -#include "object-store.h" #include "exec-cmd.h" #include "hook.h" diff --git a/builtin/grep.c b/builtin/grep.c index f1a924eade..bcb07ea7f7 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -484,7 +484,7 @@ static int grep_submodule(struct grep_opt *opt, object_type = oid_object_info(subrepo, oid, NULL); obj_read_unlock(); data = read_object_with_reference(subrepo, - oid, tree_type, + oid, OBJ_TREE, &size, NULL); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(oid)); @@ -653,7 +653,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, int hit, len; data = read_object_with_reference(opt->repo, - &obj->oid, tree_type, + &obj->oid, OBJ_TREE, &size, NULL); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid)); diff --git a/builtin/hash-object.c b/builtin/hash-object.c index 0837849288..fbae878c2b 100644 --- a/builtin/hash-object.c +++ b/builtin/hash-object.c @@ -25,7 +25,7 @@ static int hash_literally(struct object_id *oid, int fd, const char *type, unsig if (strbuf_read(&buf, fd, 4096) < 0) ret = -1; else - ret = hash_object_file_literally(buf.buf, buf.len, type, oid, + ret = write_object_file_literally(buf.buf, buf.len, type, oid, flags); strbuf_release(&buf); return ret; diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 38fb4f4e55..8a5a644744 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -453,8 +453,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size, int hdrlen; if (!is_delta_type(type)) { - hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX, - type_name(type),(uintmax_t)size) + 1; + hdrlen = format_object_header(hdr, sizeof(hdr), type, size); the_hash_algo->init_fn(&c); the_hash_algo->update_fn(&c, hdr, hdrlen); } else @@ -583,7 +582,7 @@ static void *unpack_data(struct object_entry *obj, if (!n) die(Q_("premature end of pack file, %"PRIuMAX" byte missing", "premature end of pack file, %"PRIuMAX" bytes missing", - (unsigned int)len), + len), (uintmax_t)len); from += n; len -= n; @@ -975,7 +974,7 @@ static struct base_data *resolve_delta(struct object_entry *delta_obj, if (!result_data) bad_object(delta_obj->idx.offset, _("failed to apply delta")); hash_object_file(the_hash_algo, result_data, result_size, - type_name(delta_obj->real_type), &delta_obj->idx.oid); + delta_obj->real_type, &delta_obj->idx.oid); sha1_object(result_data, NULL, result_size, delta_obj->real_type, &delta_obj->idx.oid); @@ -1419,9 +1418,8 @@ static void fix_unresolved_deltas(struct hashfile *f) if (!data) continue; - if (check_object_signature(the_repository, &d->oid, - data, size, - type_name(type), NULL)) + if (check_object_signature(the_repository, &d->oid, data, size, + type) < 0) die(_("local object %s is corrupt"), oid_to_hex(&d->oid)); /* diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index a4bfd8fc51..b9acbf5d34 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -58,7 +58,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) "Ignoring %s.", "cannot handle more than %d bases. " "Ignoring %s.", - (int)ARRAY_SIZE(bases)-1), + ARRAY_SIZE(bases)-1), (int)ARRAY_SIZE(bases)-1, argv[i]); } if (argc - i != 3) /* "--" "<head>" "<remote>" */ diff --git a/builtin/merge.c b/builtin/merge.c index a94a03384a..f178f5a3ee 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -845,15 +845,20 @@ static void prepare_to_commit(struct commit_list *remoteheads) struct strbuf msg = STRBUF_INIT; const char *index_file = get_index_file(); - if (!no_verify && run_commit_hook(0 < option_edit, index_file, "pre-merge-commit", NULL)) - abort_commit(remoteheads, NULL); - /* - * Re-read the index as pre-merge-commit hook could have updated it, - * and write it out as a tree. We must do this before we invoke - * the editor and after we invoke run_status above. - */ - if (hook_exists("pre-merge-commit")) - discard_cache(); + if (!no_verify) { + int invoked_hook; + + if (run_commit_hook(0 < option_edit, index_file, &invoked_hook, + "pre-merge-commit", NULL)) + abort_commit(remoteheads, NULL); + /* + * Re-read the index as pre-merge-commit hook could have updated it, + * and write it out as a tree. We must do this before we invoke + * the editor and after we invoke run_status above. + */ + if (invoked_hook) + discard_cache(); + } read_cache_from(index_file); strbuf_addbuf(&msg, &merge_msg); if (squash) @@ -875,7 +880,8 @@ static void prepare_to_commit(struct commit_list *remoteheads) append_signoff(&msg, ignore_non_trailer(msg.buf, msg.len), 0); write_merge_heads(remoteheads); write_file_buf(git_path_merge_msg(the_repository), msg.buf, msg.len); - if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg", + if (run_commit_hook(0 < option_edit, get_index_file(), NULL, + "prepare-commit-msg", git_path_merge_msg(the_repository), "merge", NULL)) abort_commit(remoteheads, NULL); if (0 < option_edit) { @@ -884,7 +890,7 @@ static void prepare_to_commit(struct commit_list *remoteheads) } if (!no_verify && run_commit_hook(0 < option_edit, get_index_file(), - "commit-msg", + NULL, "commit-msg", git_path_merge_msg(the_repository), NULL)) abort_commit(remoteheads, NULL); diff --git a/builtin/mktag.c b/builtin/mktag.c index c7b905c614..5d22909122 100644 --- a/builtin/mktag.c +++ b/builtin/mktag.c @@ -61,9 +61,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) type_name(*tagged_type), type_name(type)); repl = lookup_replace_object(the_repository, tagged_oid); - ret = check_object_signature(the_repository, repl, - buffer, size, type_name(*tagged_type), - NULL); + ret = check_object_signature(the_repository, repl, buffer, size, + *tagged_type); free(buffer); return ret; @@ -97,10 +96,10 @@ int cmd_mktag(int argc, const char **argv, const char *prefix) &tagged_oid, &tagged_type)) die(_("tag on stdin did not pass our strict fsck check")); - if (verify_object_in_tag(&tagged_oid, &tagged_type)) + if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0) die(_("tag on stdin did not refer to a valid object")); - if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0) + if (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0) die(_("unable to write tag file")); strbuf_release(&buf); diff --git a/builtin/mktree.c b/builtin/mktree.c index 8bdaada922..902edba6d2 100644 --- a/builtin/mktree.c +++ b/builtin/mktree.c @@ -58,7 +58,7 @@ static void write_tree(struct object_id *oid) strbuf_add(&buf, ent->oid.hash, the_hash_algo->rawsz); } - write_object_file(buf.buf, buf.len, tree_type, oid); + write_object_file(buf.buf, buf.len, OBJ_TREE, oid); strbuf_release(&buf); } diff --git a/builtin/name-rev.c b/builtin/name-rev.c index 929591269d..c59b5699fe 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -9,6 +9,7 @@ #include "prio-queue.h" #include "hash-lookup.h" #include "commit-slab.h" +#include "commit-graph.h" /* * One day. See the 'name a rev shortly after epoch' test in t6120 when @@ -26,9 +27,58 @@ struct rev_name { define_commit_slab(commit_rev_name, struct rev_name); +static timestamp_t generation_cutoff = GENERATION_NUMBER_INFINITY; static timestamp_t cutoff = TIME_MAX; static struct commit_rev_name rev_names; +/* Disable the cutoff checks entirely */ +static void disable_cutoff(void) +{ + generation_cutoff = 0; + cutoff = 0; +} + +/* Cutoff searching any commits older than this one */ +static void set_commit_cutoff(struct commit *commit) +{ + + if (cutoff > commit->date) + cutoff = commit->date; + + if (generation_cutoff) { + timestamp_t generation = commit_graph_generation(commit); + + if (generation_cutoff > generation) + generation_cutoff = generation; + } +} + +/* adjust the commit date cutoff with a slop to allow for slightly incorrect + * commit timestamps in case of clock skew. + */ +static void adjust_cutoff_timestamp_for_slop(void) +{ + if (cutoff) { + /* check for undeflow */ + if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP) + cutoff = cutoff - CUTOFF_DATE_SLOP; + else + cutoff = TIME_MIN; + } +} + +/* Check if a commit is before the cutoff. Prioritize generation numbers + * first, but use the commit timestamp if we lack generation data. + */ +static int commit_is_before_cutoff(struct commit *commit) +{ + if (generation_cutoff < GENERATION_NUMBER_INFINITY) + return generation_cutoff && + commit_graph_generation(commit) < generation_cutoff; + + return commit->date < cutoff; +} + /* How many generations are maximally preferred over _one_ merge traversal? */ #define MERGE_TRAVERSAL_WEIGHT 65535 @@ -151,7 +201,7 @@ static void name_rev(struct commit *start_commit, struct rev_name *start_name; parse_commit(start_commit); - if (start_commit->date < cutoff) + if (commit_is_before_cutoff(start_commit)) return; start_name = create_or_update_name(start_commit, taggerdate, 0, 0, @@ -181,7 +231,7 @@ static void name_rev(struct commit *start_commit, int generation, distance; parse_commit(parent); - if (parent->date < cutoff) + if (commit_is_before_cutoff(parent)) continue; if (parent_number > 1) { @@ -568,7 +618,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) usage_with_options(name_rev_usage, opts); } if (all || annotate_stdin) - cutoff = 0; + disable_cutoff(); for (; argc; argc--, argv++) { struct object_id oid; @@ -596,10 +646,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) continue; } - if (commit) { - if (cutoff > commit->date) - cutoff = commit->date; - } + if (commit) + set_commit_cutoff(commit); if (peel_tag) { if (!commit) { @@ -612,13 +660,8 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) add_object_array(object, *argv, &revs); } - if (cutoff) { - /* check for undeflow */ - if (cutoff > TIME_MIN + CUTOFF_DATE_SLOP) - cutoff = cutoff - CUTOFF_DATE_SLOP; - else - cutoff = TIME_MIN; - } + adjust_cutoff_timestamp_for_slop(); + for_each_ref(name_ref, &data); name_tips(); diff --git a/builtin/notes.c b/builtin/notes.c index f99593a185..a3d0d15a22 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -199,7 +199,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * static void write_note_data(struct note_data *d, struct object_id *oid) { - if (write_object_file(d->buf.buf, d->buf.len, blob_type, oid)) { + if (write_object_file(d->buf.buf, d->buf.len, OBJ_BLOB, oid)) { int status = die_message(_("unable to write note object")); if (d->edit_path) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 178e611f09..829ca359cf 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1802,7 +1802,7 @@ static void add_preferred_base(struct object_id *oid) return; data = read_object_with_reference(the_repository, oid, - tree_type, &size, &tree_oid); + OBJ_TREE, &size, &tree_oid); if (!data) return; @@ -3651,7 +3651,7 @@ static int pack_options_allow_reuse(void) static int get_object_list_from_bitmap(struct rev_info *revs) { - if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options, 0))) + if (!(bitmap_git = prepare_bitmap_walk(revs, 0))) return -1; if (pack_options_allow_reuse() && @@ -3727,6 +3727,7 @@ static void get_object_list(int ac, const char **av) repo_init_revisions(the_repository, &revs, NULL); save_commit_buffer = 0; setup_revisions(ac, av, &revs, &s_r_opt); + list_objects_filter_copy(&revs.filter, &filter_options); /* make sure shallows are read */ is_repository_shallow(the_repository); @@ -3777,9 +3778,9 @@ static void get_object_list(int ac, const char **av) if (!fn_show_object) fn_show_object = show_object; - traverse_commit_list_filtered(&filter_options, &revs, - show_commit, fn_show_object, NULL, - NULL); + traverse_commit_list(&revs, + show_commit, fn_show_object, + NULL); if (unpack_unreachable_expiration) { revs.ignore_missing_links = 1; diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 2109c4c9e5..9f1f33e954 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -160,15 +160,22 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) argc = parse_options(argc, argv, cmd_prefix, read_tree_options, read_tree_usage, 0); - hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); - prefix_set = opts.prefix ? 1 : 0; if (1 < opts.merge + opts.reset + prefix_set) die("Which one? -m, --reset, or --prefix?"); + /* Prefix should not start with a directory separator */ + if (opts.prefix && opts.prefix[0] == '/') + die("Invalid prefix, prefix cannot start with '/'"); + if (opts.reset) opts.reset = UNPACK_RESET_OVERWRITE_UNTRACKED; + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + /* * NEEDSWORK * @@ -210,6 +217,9 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (opts.merge && !opts.index_only) setup_work_tree(); + if (opts.skip_sparse_checkout) + ensure_full_index(&the_index); + if (opts.merge) { switch (stage - 1) { case 0: diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index d10aeb7e78..9aabffa1af 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -749,7 +749,7 @@ static void prepare_push_cert_sha1(struct child_process *proc) int bogs /* beginning_of_gpg_sig */; already_done = 1; - if (write_object_file(push_cert.buf, push_cert.len, "blob", + if (write_object_file(push_cert.buf, push_cert.len, OBJ_BLOB, &push_cert_oid)) oidclr(&push_cert_oid); @@ -813,13 +813,14 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, proc.trace2_hook_name = hook_name; if (feed_state->push_options) { - int i; + size_t i; for (i = 0; i < feed_state->push_options->nr; i++) strvec_pushf(&proc.env_array, - "GIT_PUSH_OPTION_%d=%s", i, + "GIT_PUSH_OPTION_%"PRIuMAX"=%s", + (uintmax_t)i, feed_state->push_options->items[i].string); - strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d", - feed_state->push_options->nr); + strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%"PRIuMAX"", + (uintmax_t)feed_state->push_options->nr); } else strvec_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT"); @@ -1408,10 +1409,12 @@ static const char *push_to_deploy(unsigned char *sha1, static const char *push_to_checkout_hook = "push-to-checkout"; static const char *push_to_checkout(unsigned char *hash, + int *invoked_hook, struct strvec *env, const char *work_tree) { struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT; + opt.invoked_hook = invoked_hook; strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree)); strvec_pushv(&opt.env, env->v); @@ -1426,6 +1429,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w { const char *retval, *git_dir; struct strvec env = STRVEC_INIT; + int invoked_hook; if (!worktree || !worktree->path) BUG("worktree->path must be non-NULL"); @@ -1436,10 +1440,9 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir)); - if (!hook_exists(push_to_checkout_hook)) + retval = push_to_checkout(sha1, &invoked_hook, &env, worktree->path); + if (!invoked_hook) retval = push_to_deploy(sha1, &env, worktree->path); - else - retval = push_to_checkout(sha1, &env, worktree->path); strvec_clear(&env); return retval; diff --git a/builtin/reflog.c b/builtin/reflog.c index 016466852f..9407f835cb 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -1,16 +1,9 @@ #include "builtin.h" #include "config.h" -#include "lockfile.h" -#include "object-store.h" -#include "repository.h" -#include "commit.h" -#include "refs.h" -#include "dir.h" -#include "tree-walk.h" -#include "diff.h" #include "revision.h" #include "reachable.h" #include "worktree.h" +#include "reflog.h" static const char reflog_exists_usage[] = N_("git reflog exists <ref>"); @@ -18,404 +11,11 @@ N_("git reflog exists <ref>"); static timestamp_t default_reflog_expire; static timestamp_t default_reflog_expire_unreachable; -struct cmd_reflog_expire_cb { - int stalefix; - int explicit_expiry; - timestamp_t expire_total; - timestamp_t expire_unreachable; - int recno; -}; - -struct expire_reflog_policy_cb { - enum { - UE_NORMAL, - UE_ALWAYS, - UE_HEAD - } unreachable_expire_kind; - struct commit_list *mark_list; - unsigned long mark_limit; - struct cmd_reflog_expire_cb cmd; - struct commit *tip_commit; - struct commit_list *tips; - unsigned int dry_run:1; -}; - struct worktree_reflogs { struct worktree *worktree; struct string_list reflogs; }; -/* Remember to update object flag allocation in object.h */ -#define INCOMPLETE (1u<<10) -#define STUDYING (1u<<11) -#define REACHABLE (1u<<12) - -static int tree_is_complete(const struct object_id *oid) -{ - struct tree_desc desc; - struct name_entry entry; - int complete; - struct tree *tree; - - tree = lookup_tree(the_repository, oid); - if (!tree) - return 0; - if (tree->object.flags & SEEN) - return 1; - if (tree->object.flags & INCOMPLETE) - return 0; - - if (!tree->buffer) { - enum object_type type; - unsigned long size; - void *data = read_object_file(oid, &type, &size); - if (!data) { - tree->object.flags |= INCOMPLETE; - return 0; - } - tree->buffer = data; - tree->size = size; - } - init_tree_desc(&desc, tree->buffer, tree->size); - complete = 1; - while (tree_entry(&desc, &entry)) { - if (!has_object_file(&entry.oid) || - (S_ISDIR(entry.mode) && !tree_is_complete(&entry.oid))) { - tree->object.flags |= INCOMPLETE; - complete = 0; - } - } - free_tree_buffer(tree); - - if (complete) - tree->object.flags |= SEEN; - return complete; -} - -static int commit_is_complete(struct commit *commit) -{ - struct object_array study; - struct object_array found; - int is_incomplete = 0; - int i; - - /* early return */ - if (commit->object.flags & SEEN) - return 1; - if (commit->object.flags & INCOMPLETE) - return 0; - /* - * Find all commits that are reachable and are not marked as - * SEEN. Then make sure the trees and blobs contained are - * complete. After that, mark these commits also as SEEN. - * If some of the objects that are needed to complete this - * commit are missing, mark this commit as INCOMPLETE. - */ - memset(&study, 0, sizeof(study)); - memset(&found, 0, sizeof(found)); - add_object_array(&commit->object, NULL, &study); - add_object_array(&commit->object, NULL, &found); - commit->object.flags |= STUDYING; - while (study.nr) { - struct commit *c; - struct commit_list *parent; - - c = (struct commit *)object_array_pop(&study); - if (!c->object.parsed && !parse_object(the_repository, &c->object.oid)) - c->object.flags |= INCOMPLETE; - - if (c->object.flags & INCOMPLETE) { - is_incomplete = 1; - break; - } - else if (c->object.flags & SEEN) - continue; - for (parent = c->parents; parent; parent = parent->next) { - struct commit *p = parent->item; - if (p->object.flags & STUDYING) - continue; - p->object.flags |= STUDYING; - add_object_array(&p->object, NULL, &study); - add_object_array(&p->object, NULL, &found); - } - } - if (!is_incomplete) { - /* - * make sure all commits in "found" array have all the - * necessary objects. - */ - for (i = 0; i < found.nr; i++) { - struct commit *c = - (struct commit *)found.objects[i].item; - if (!tree_is_complete(get_commit_tree_oid(c))) { - is_incomplete = 1; - c->object.flags |= INCOMPLETE; - } - } - if (!is_incomplete) { - /* mark all found commits as complete, iow SEEN */ - for (i = 0; i < found.nr; i++) - found.objects[i].item->flags |= SEEN; - } - } - /* clear flags from the objects we traversed */ - for (i = 0; i < found.nr; i++) - found.objects[i].item->flags &= ~STUDYING; - if (is_incomplete) - commit->object.flags |= INCOMPLETE; - else { - /* - * If we come here, we have (1) traversed the ancestry chain - * from the "commit" until we reach SEEN commits (which are - * known to be complete), and (2) made sure that the commits - * encountered during the above traversal refer to trees that - * are complete. Which means that we know *all* the commits - * we have seen during this process are complete. - */ - for (i = 0; i < found.nr; i++) - found.objects[i].item->flags |= SEEN; - } - /* free object arrays */ - object_array_clear(&study); - object_array_clear(&found); - return !is_incomplete; -} - -static int keep_entry(struct commit **it, struct object_id *oid) -{ - struct commit *commit; - - if (is_null_oid(oid)) - return 1; - commit = lookup_commit_reference_gently(the_repository, oid, 1); - if (!commit) - return 0; - - /* - * Make sure everything in this commit exists. - * - * We have walked all the objects reachable from the refs - * and cache earlier. The commits reachable by this commit - * must meet SEEN commits -- and then we should mark them as - * SEEN as well. - */ - if (!commit_is_complete(commit)) - return 0; - *it = commit; - return 1; -} - -/* - * Starting from commits in the cb->mark_list, mark commits that are - * reachable from them. Stop the traversal at commits older than - * the expire_limit and queue them back, so that the caller can call - * us again to restart the traversal with longer expire_limit. - */ -static void mark_reachable(struct expire_reflog_policy_cb *cb) -{ - struct commit_list *pending; - timestamp_t expire_limit = cb->mark_limit; - struct commit_list *leftover = NULL; - - for (pending = cb->mark_list; pending; pending = pending->next) - pending->item->object.flags &= ~REACHABLE; - - pending = cb->mark_list; - while (pending) { - struct commit_list *parent; - struct commit *commit = pop_commit(&pending); - if (commit->object.flags & REACHABLE) - continue; - if (parse_commit(commit)) - continue; - commit->object.flags |= REACHABLE; - if (commit->date < expire_limit) { - commit_list_insert(commit, &leftover); - continue; - } - commit->object.flags |= REACHABLE; - parent = commit->parents; - while (parent) { - commit = parent->item; - parent = parent->next; - if (commit->object.flags & REACHABLE) - continue; - commit_list_insert(commit, &pending); - } - } - cb->mark_list = leftover; -} - -static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit, struct object_id *oid) -{ - /* - * We may or may not have the commit yet - if not, look it - * up using the supplied sha1. - */ - if (!commit) { - if (is_null_oid(oid)) - return 0; - - commit = lookup_commit_reference_gently(the_repository, oid, - 1); - - /* Not a commit -- keep it */ - if (!commit) - return 0; - } - - /* Reachable from the current ref? Don't prune. */ - if (commit->object.flags & REACHABLE) - return 0; - - if (cb->mark_list && cb->mark_limit) { - cb->mark_limit = 0; /* dig down to the root */ - mark_reachable(cb); - } - - return !(commit->object.flags & REACHABLE); -} - -/* - * Return true iff the specified reflog entry should be expired. - */ -static int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, - const char *email, timestamp_t timestamp, int tz, - const char *message, void *cb_data) -{ - struct expire_reflog_policy_cb *cb = cb_data; - struct commit *old_commit, *new_commit; - - if (timestamp < cb->cmd.expire_total) - return 1; - - old_commit = new_commit = NULL; - if (cb->cmd.stalefix && - (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid))) - return 1; - - if (timestamp < cb->cmd.expire_unreachable) { - switch (cb->unreachable_expire_kind) { - case UE_ALWAYS: - return 1; - case UE_NORMAL: - case UE_HEAD: - if (unreachable(cb, old_commit, ooid) || unreachable(cb, new_commit, noid)) - return 1; - break; - } - } - - if (cb->cmd.recno && --(cb->cmd.recno) == 0) - return 1; - - return 0; -} - -static int should_expire_reflog_ent_verbose(struct object_id *ooid, - struct object_id *noid, - const char *email, - timestamp_t timestamp, int tz, - const char *message, void *cb_data) -{ - struct expire_reflog_policy_cb *cb = cb_data; - int expire; - - expire = should_expire_reflog_ent(ooid, noid, email, timestamp, tz, - message, cb); - - if (!expire) - printf("keep %s", message); - else if (cb->dry_run) - printf("would prune %s", message); - else - printf("prune %s", message); - - return expire; -} - -static int push_tip_to_list(const char *refname, const struct object_id *oid, - int flags, void *cb_data) -{ - struct commit_list **list = cb_data; - struct commit *tip_commit; - if (flags & REF_ISSYMREF) - return 0; - tip_commit = lookup_commit_reference_gently(the_repository, oid, 1); - if (!tip_commit) - return 0; - commit_list_insert(tip_commit, list); - return 0; -} - -static int is_head(const char *refname) -{ - switch (ref_type(refname)) { - case REF_TYPE_OTHER_PSEUDOREF: - case REF_TYPE_MAIN_PSEUDOREF: - if (parse_worktree_ref(refname, NULL, NULL, &refname)) - BUG("not a worktree ref: %s", refname); - break; - default: - break; - } - return !strcmp(refname, "HEAD"); -} - -static void reflog_expiry_prepare(const char *refname, - const struct object_id *oid, - void *cb_data) -{ - struct expire_reflog_policy_cb *cb = cb_data; - struct commit_list *elem; - struct commit *commit = NULL; - - if (!cb->cmd.expire_unreachable || is_head(refname)) { - cb->unreachable_expire_kind = UE_HEAD; - } else { - commit = lookup_commit(the_repository, oid); - cb->unreachable_expire_kind = commit ? UE_NORMAL : UE_ALWAYS; - } - - if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) - cb->unreachable_expire_kind = UE_ALWAYS; - - switch (cb->unreachable_expire_kind) { - case UE_ALWAYS: - return; - case UE_HEAD: - for_each_ref(push_tip_to_list, &cb->tips); - for (elem = cb->tips; elem; elem = elem->next) - commit_list_insert(elem->item, &cb->mark_list); - break; - case UE_NORMAL: - commit_list_insert(commit, &cb->mark_list); - /* For reflog_expiry_cleanup() below */ - cb->tip_commit = commit; - } - cb->mark_limit = cb->cmd.expire_total; - mark_reachable(cb); -} - -static void reflog_expiry_cleanup(void *cb_data) -{ - struct expire_reflog_policy_cb *cb = cb_data; - struct commit_list *elem; - - switch (cb->unreachable_expire_kind) { - case UE_ALWAYS: - return; - case UE_HEAD: - for (elem = cb->tips; elem; elem = elem->next) - clear_commit_marks(elem->item, REACHABLE); - free_commit_list(cb->tips); - break; - case UE_NORMAL: - clear_commit_marks(cb->tip_commit, REACHABLE); - break; - } -} - static int collect_reflog(const char *ref, const struct object_id *oid, int unused, void *cb_data) { struct worktree_reflogs *cb = cb_data; @@ -704,16 +304,6 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) return status; } -static int count_reflog_ent(struct object_id *ooid, struct object_id *noid, - const char *email, timestamp_t timestamp, int tz, - const char *message, void *cb_data) -{ - struct cmd_reflog_expire_cb *cb = cb_data; - if (!cb->expire_total || timestamp < cb->expire_total) - cb->recno++; - return 0; -} - static const char * reflog_delete_usage[] = { N_("git reflog delete [--rewrite] [--updateref] " "[--dry-run | -n] [--verbose] <refs>..."), @@ -722,11 +312,10 @@ static const char * reflog_delete_usage[] = { static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) { - struct cmd_reflog_expire_cb cmd = { 0 }; int i, status = 0; unsigned int flags = 0; int verbose = 0; - reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent; + const struct option options[] = { OPT_BIT(0, "dry-run", &flags, N_("do not actually prune any entries"), EXPIRE_REFLOGS_DRY_RUN), @@ -742,48 +331,12 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, reflog_delete_usage, 0); - if (verbose) - should_prune_fn = should_expire_reflog_ent_verbose; - if (argc < 1) return error(_("no reflog specified to delete")); - for (i = 0; i < argc; i++) { - const char *spec = strstr(argv[i], "@{"); - char *ep, *ref; - int recno; - struct expire_reflog_policy_cb cb = { - .dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN), - }; - - if (!spec) { - status |= error(_("not a reflog: %s"), argv[i]); - continue; - } + for (i = 0; i < argc; i++) + status |= reflog_delete(argv[i], flags, verbose); - if (!dwim_log(argv[i], spec - argv[i], NULL, &ref)) { - status |= error(_("no reflog for '%s'"), argv[i]); - continue; - } - - recno = strtoul(spec + 2, &ep, 10); - if (*ep == '}') { - cmd.recno = -recno; - for_each_reflog_ent(ref, count_reflog_ent, &cmd); - } else { - cmd.expire_total = approxidate(spec + 2); - for_each_reflog_ent(ref, count_reflog_ent, &cmd); - cmd.expire_total = 0; - } - - cb.cmd = cmd; - status |= reflog_expire(ref, flags, - reflog_expiry_prepare, - should_prune_fn, - reflog_expiry_cleanup, - &cb); - free(ref); - } return status; } diff --git a/builtin/remote.c b/builtin/remote.c index 6f27ddc47b..5f4cde9d78 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -12,11 +12,12 @@ #include "object-store.h" #include "strvec.h" #include "commit-reach.h" +#include "progress.h" static const char * const builtin_remote_usage[] = { "git remote [-v | --verbose]", N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>"), - N_("git remote rename <old> <new>"), + N_("git remote rename [--[no-]progress] <old> <new>"), N_("git remote remove <name>"), N_("git remote set-head <name> (-a | --auto | -d | --delete | <branch>)"), N_("git remote [-v | --verbose] show [-n] <name>"), @@ -36,7 +37,7 @@ static const char * const builtin_remote_add_usage[] = { }; static const char * const builtin_remote_rename_usage[] = { - N_("git remote rename <old> <new>"), + N_("git remote rename [--[no-]progress] <old> <new>"), NULL }; @@ -571,6 +572,7 @@ struct rename_info { const char *old_name; const char *new_name; struct string_list *remote_branches; + uint32_t symrefs_nr; }; static int read_remote_branches(const char *refname, @@ -587,10 +589,12 @@ static int read_remote_branches(const char *refname, item = string_list_append(rename->remote_branches, refname); symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING, NULL, &flag); - if (symref && (flag & REF_ISSYMREF)) + if (symref && (flag & REF_ISSYMREF)) { item->util = xstrdup(symref); - else + rename->symrefs_nr++; + } else { item->util = NULL; + } } strbuf_release(&buf); @@ -674,7 +678,9 @@ static void handle_push_default(const char* old_name, const char* new_name) static int mv(int argc, const char **argv) { + int show_progress = isatty(2); struct option options[] = { + OPT_BOOL(0, "progress", &show_progress, N_("force progress reporting")), OPT_END() }; struct remote *oldremote, *newremote; @@ -682,14 +688,19 @@ static int mv(int argc, const char **argv) old_remote_context = STRBUF_INIT; struct string_list remote_branches = STRING_LIST_INIT_DUP; struct rename_info rename; - int i, refspec_updated = 0; + int i, refs_renamed_nr = 0, refspec_updated = 0; + struct progress *progress = NULL; + + argc = parse_options(argc, argv, NULL, options, + builtin_remote_rename_usage, 0); - if (argc != 3) + if (argc != 2) usage_with_options(builtin_remote_rename_usage, options); - rename.old_name = argv[1]; - rename.new_name = argv[2]; + rename.old_name = argv[0]; + rename.new_name = argv[1]; rename.remote_branches = &remote_branches; + rename.symrefs_nr = 0; oldremote = remote_get(rename.old_name); if (!remote_is_configured(oldremote, 1)) { @@ -764,15 +775,26 @@ static int mv(int argc, const char **argv) * the new symrefs. */ for_each_ref(read_remote_branches, &rename); + if (show_progress) { + /* + * Count symrefs twice, since "renaming" them is done by + * deleting and recreating them in two separate passes. + */ + progress = start_progress(_("Renaming remote references"), + rename.remote_branches->nr + rename.symrefs_nr); + } for (i = 0; i < remote_branches.nr; i++) { struct string_list_item *item = remote_branches.items + i; - int flag = 0; + struct strbuf referent = STRBUF_INIT; - read_ref_full(item->string, RESOLVE_REF_READING, NULL, &flag); - if (!(flag & REF_ISSYMREF)) + if (refs_read_symbolic_ref(get_main_ref_store(the_repository), item->string, + &referent)) continue; if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF)) die(_("deleting '%s' failed"), item->string); + + strbuf_release(&referent); + display_progress(progress, ++refs_renamed_nr); } for (i = 0; i < remote_branches.nr; i++) { struct string_list_item *item = remote_branches.items + i; @@ -788,6 +810,7 @@ static int mv(int argc, const char **argv) item->string, buf.buf); if (rename_ref(item->string, buf.buf, buf2.buf)) die(_("renaming '%s' failed"), item->string); + display_progress(progress, ++refs_renamed_nr); } for (i = 0; i < remote_branches.nr; i++) { struct string_list_item *item = remote_branches.items + i; @@ -807,7 +830,9 @@ static int mv(int argc, const char **argv) item->string, buf.buf); if (create_symref(buf.buf, buf2.buf, buf3.buf)) die(_("creating '%s' failed"), buf.buf); + display_progress(progress, ++refs_renamed_nr); } + stop_progress(&progress); string_list_clear(&remote_branches, 1); handle_push_default(rename.old_name, rename.new_name); diff --git a/builtin/repack.c b/builtin/repack.c index da1e364a75..d1a563d5b6 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -22,6 +22,7 @@ static int delta_base_offset = 1; static int pack_kept_objects = -1; static int write_bitmaps = -1; static int use_delta_islands; +static int run_update_server_info = 1; static char *packdir, *packtmp_name, *packtmp; static const char *const git_repack_usage[] = { @@ -54,6 +55,10 @@ static int repack_config(const char *var, const char *value, void *cb) use_delta_islands = git_config_bool(var, value); return 0; } + if (strcmp(var, "repack.updateserverinfo") == 0) { + run_update_server_info = git_config_bool(var, value); + return 0; + } return git_default_config(var, value, cb); } @@ -620,7 +625,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *unpack_unreachable = NULL; int keep_unreachable = 0; struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; - int no_update_server_info = 0; struct pack_objects_args po_args = {NULL}; int geometric_factor = 0; int write_midx = 0; @@ -637,8 +641,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("pass --no-reuse-delta to git-pack-objects")), OPT_BOOL('F', NULL, &po_args.no_reuse_object, N_("pass --no-reuse-object to git-pack-objects")), - OPT_BOOL('n', NULL, &no_update_server_info, - N_("do not run git-update-server-info")), + OPT_NEGBIT('n', NULL, &run_update_server_info, + N_("do not run git-update-server-info"), 1), OPT__QUIET(&po_args.quiet, N_("be quiet")), OPT_BOOL('l', "local", &po_args.local, N_("pass --local to git-pack-objects")), @@ -939,7 +943,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) prune_shallow(PRUNE_QUICK); } - if (!no_update_server_info) + if (run_update_server_info) update_server_info(0); remove_temporary_files(); diff --git a/builtin/replace.c b/builtin/replace.c index ac92337c0e..5068f4f0b2 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -409,7 +409,7 @@ static int check_one_mergetag(struct commit *commit, int i; hash_object_file(the_hash_algo, extra->value, extra->len, - type_name(OBJ_TAG), &tag_oid); + OBJ_TAG, &tag_oid); tag = lookup_tag(the_repository, &tag_oid); if (!tag) return error(_("bad mergetag in commit '%s'"), ref); @@ -474,7 +474,7 @@ static int create_graft(int argc, const char **argv, int force, int gentle) return -1; } - if (write_object_file(buf.buf, buf.len, commit_type, &new_oid)) { + if (write_object_file(buf.buf, buf.len, OBJ_COMMIT, &new_oid)) { strbuf_release(&buf); return error(_("could not write replacement commit for: '%s'"), old_ref); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 38528c7f15..572da1472e 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -62,7 +62,6 @@ static const char rev_list_usage[] = static struct progress *progress; static unsigned progress_counter; -static struct list_objects_filter_options filter_options; static struct oidset omitted_objects; static int arg_print_omitted; /* print objects omitted by filter */ @@ -400,7 +399,6 @@ static inline int parse_missing_action_value(const char *value) } static int try_bitmap_count(struct rev_info *revs, - struct list_objects_filter_options *filter, int filter_provided_objects) { uint32_t commit_count = 0, @@ -436,7 +434,7 @@ static int try_bitmap_count(struct rev_info *revs, */ max_count = revs->max_count; - bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects); + bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects); if (!bitmap_git) return -1; @@ -453,7 +451,6 @@ static int try_bitmap_count(struct rev_info *revs, } static int try_bitmap_traversal(struct rev_info *revs, - struct list_objects_filter_options *filter, int filter_provided_objects) { struct bitmap_index *bitmap_git; @@ -465,7 +462,7 @@ static int try_bitmap_traversal(struct rev_info *revs, if (revs->max_count >= 0) return -1; - bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects); + bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects); if (!bitmap_git) return -1; @@ -475,7 +472,6 @@ static int try_bitmap_traversal(struct rev_info *revs, } static int try_bitmap_disk_usage(struct rev_info *revs, - struct list_objects_filter_options *filter, int filter_provided_objects) { struct bitmap_index *bitmap_git; @@ -483,7 +479,7 @@ static int try_bitmap_disk_usage(struct rev_info *revs, if (!show_disk_usage) return -1; - bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects); + bitmap_git = prepare_bitmap_walk(revs, filter_provided_objects); if (!bitmap_git) return -1; @@ -595,17 +591,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) show_progress = arg; continue; } - - if (skip_prefix(arg, ("--" CL_ARG__FILTER "="), &arg)) { - parse_list_objects_filter(&filter_options, arg); - if (filter_options.choice && !revs.blob_objects) - die(_("object filtering requires --objects")); - continue; - } - if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) { - list_objects_filter_set_no_filter(&filter_options); - continue; - } if (!strcmp(arg, "--filter-provided-objects")) { filter_provided_objects = 1; continue; @@ -688,11 +673,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) progress = start_delayed_progress(show_progress, 0); if (use_bitmap_index) { - if (!try_bitmap_count(&revs, &filter_options, filter_provided_objects)) + if (!try_bitmap_count(&revs, filter_provided_objects)) return 0; - if (!try_bitmap_disk_usage(&revs, &filter_options, filter_provided_objects)) + if (!try_bitmap_disk_usage(&revs, filter_provided_objects)) return 0; - if (!try_bitmap_traversal(&revs, &filter_options, filter_provided_objects)) + if (!try_bitmap_traversal(&revs, filter_provided_objects)) return 0; } @@ -733,7 +718,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE); traverse_commit_list_filtered( - &filter_options, &revs, show_commit, show_object, &info, + &revs, show_commit, show_object, &info, (arg_print_omitted ? &omitted_objects : NULL)); if (arg_print_omitted) { diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 228d782754..26c5c0cf93 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -435,7 +435,7 @@ static void add_wrapped_shortlog_msg(struct strbuf *sb, const char *s, void shortlog_output(struct shortlog *log) { - int i, j; + size_t i, j; struct strbuf sb = STRBUF_INIT; if (log->sort_by_number) @@ -448,10 +448,10 @@ void shortlog_output(struct shortlog *log) (int)UTIL_TO_INT(item), item->string); } else { struct string_list *onelines = item->util; - fprintf(log->file, "%s (%d):\n", - item->string, onelines->nr); - for (j = onelines->nr - 1; j >= 0; j--) { - const char *msg = onelines->items[j].string; + fprintf(log->file, "%s (%"PRIuMAX"):\n", + item->string, (uintmax_t)onelines->nr); + for (j = onelines->nr; j >= 1; j--) { + const char *msg = onelines->items[j - 1].string; if (log->wrap_lines) { strbuf_reset(&sb); diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c index 7f02e4352a..0217d44c5b 100644 --- a/builtin/sparse-checkout.c +++ b/builtin/sparse-checkout.c @@ -8,7 +8,6 @@ #include "run-command.h" #include "strbuf.h" #include "string-list.h" -#include "cache.h" #include "cache-tree.h" #include "lockfile.h" #include "resolve-undo.h" diff --git a/builtin/stash.c b/builtin/stash.c index 3e8af210fd..ccdfdab44b 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -16,7 +16,7 @@ #include "log-tree.h" #include "diffcore.h" #include "exec-cmd.h" -#include "entry.h" +#include "reflog.h" #define INCLUDE_ALL_FILES 2 @@ -634,20 +634,9 @@ static int reflog_is_empty(const char *refname) static int do_drop_stash(struct stash_info *info, int quiet) { - int ret; - struct child_process cp_reflog = CHILD_PROCESS_INIT; - - /* - * reflog does not provide a simple function for deleting refs. One will - * need to be added to avoid implementing too much reflog code here - */ - - cp_reflog.git_cmd = 1; - strvec_pushl(&cp_reflog.args, "reflog", "delete", "--updateref", - "--rewrite", NULL); - strvec_push(&cp_reflog.args, info->revision.buf); - ret = run_command(&cp_reflog); - if (!ret) { + if (!reflog_delete(info->revision.buf, + EXPIRE_REFLOGS_REWRITE | EXPIRE_REFLOGS_UPDATE_REF, + 0)) { if (!quiet) printf_ln(_("Dropped %s (%s)"), info->revision.buf, oid_to_hex(&info->w_commit)); diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 2f7c58362b..5301612d24 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -31,11 +31,13 @@ typedef void (*each_submodule_fn)(const struct cache_entry *list_item, void *cb_data); -static char *get_default_remote(void) +static char *repo_get_default_remote(struct repository *repo) { char *dest = NULL, *ret; struct strbuf sb = STRBUF_INIT; - const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL); + struct ref_store *store = get_main_ref_store(repo); + const char *refname = refs_resolve_ref_unsafe(store, "HEAD", 0, NULL, + NULL); if (!refname) die(_("No such ref: %s"), "HEAD"); @@ -48,7 +50,7 @@ static char *get_default_remote(void) die(_("Expecting a full ref name, got %s"), refname); strbuf_addf(&sb, "branch.%s.remote", refname); - if (git_config_get_string(sb.buf, &dest)) + if (repo_config_get_string(repo, sb.buf, &dest)) ret = xstrdup("origin"); else ret = dest; @@ -57,19 +59,17 @@ static char *get_default_remote(void) return ret; } -static int print_default_remote(int argc, const char **argv, const char *prefix) +static char *get_default_remote_submodule(const char *module_path) { - char *remote; - - if (argc != 1) - die(_("submodule--helper print-default-remote takes no arguments")); + struct repository subrepo; - remote = get_default_remote(); - if (remote) - printf("%s\n", remote); + repo_submodule_init(&subrepo, the_repository, module_path, null_oid()); + return repo_get_default_remote(&subrepo); +} - free(remote); - return 0; +static char *get_default_remote(void) +{ + return repo_get_default_remote(the_repository); } static int starts_with_dot_slash(const char *str) @@ -247,11 +247,10 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr return 0; } -/* the result should be freed by the caller. */ -static char *get_submodule_displaypath(const char *path, const char *prefix) +static char *do_get_submodule_displaypath(const char *path, + const char *prefix, + const char *super_prefix) { - const char *super_prefix = get_super_prefix(); - if (prefix && super_prefix) { BUG("cannot have prefix '%s' and superprefix '%s'", prefix, super_prefix); @@ -267,6 +266,13 @@ static char *get_submodule_displaypath(const char *path, const char *prefix) } } +/* the result should be freed by the caller. */ +static char *get_submodule_displaypath(const char *path, const char *prefix) +{ + const char *super_prefix = get_super_prefix(); + return do_get_submodule_displaypath(path, prefix, super_prefix); +} + static char *compute_rev_name(const char *sub_path, const char* object_id) { struct strbuf sb = STRBUF_INIT; @@ -588,18 +594,22 @@ static int module_foreach(int argc, const char **argv, const char *prefix) struct init_cb { const char *prefix; + const char *superprefix; unsigned int flags; }; #define INIT_CB_INIT { 0 } static void init_submodule(const char *path, const char *prefix, - unsigned int flags) + const char *superprefix, unsigned int flags) { const struct submodule *sub; struct strbuf sb = STRBUF_INIT; char *upd = NULL, *url = NULL, *displaypath; - displaypath = get_submodule_displaypath(path, prefix); + /* try superprefix from the environment, if it is not passed explicitly */ + if (!superprefix) + superprefix = get_super_prefix(); + displaypath = do_get_submodule_displaypath(path, prefix, superprefix); sub = submodule_from_path(the_repository, null_oid(), path); @@ -673,7 +683,7 @@ static void init_submodule(const char *path, const char *prefix, static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data) { struct init_cb *info = cb_data; - init_submodule(list_item->name, info->prefix, info->flags); + init_submodule(list_item->name, info->prefix, info->superprefix, info->flags); } static int module_init(int argc, const char **argv, const char *prefix) @@ -1343,9 +1353,8 @@ static void sync_submodule(const char *path, const char *prefix, { const struct submodule *sub; char *remote_key = NULL; - char *sub_origin_url, *super_config_url, *displaypath; + char *sub_origin_url, *super_config_url, *displaypath, *default_remote; struct strbuf sb = STRBUF_INIT; - struct child_process cp = CHILD_PROCESS_INIT; char *sub_config_path = NULL; if (!is_submodule_active(the_repository, path)) @@ -1384,21 +1393,15 @@ static void sync_submodule(const char *path, const char *prefix, if (!is_submodule_populated_gently(path, NULL)) goto cleanup; - prepare_submodule_repo_env(&cp.env_array); - cp.git_cmd = 1; - cp.dir = path; - strvec_pushl(&cp.args, "submodule--helper", - "print-default-remote", NULL); - strbuf_reset(&sb); - if (capture_command(&cp, &sb, 0)) + default_remote = get_default_remote_submodule(path); + if (!default_remote) die(_("failed to get the default remote for submodule '%s'"), path); - strbuf_strip_suffix(&sb, "\n"); - remote_key = xstrfmt("remote.%s.url", sb.buf); + remote_key = xstrfmt("remote.%s.url", default_remote); + free(default_remote); - strbuf_reset(&sb); submodule_to_gitdir(&sb, path); strbuf_addstr(&sb, "/config"); @@ -1957,29 +1960,6 @@ static void determine_submodule_update_strategy(struct repository *r, free(key); } -static int module_update_module_mode(int argc, const char **argv, const char *prefix) -{ - const char *path, *update = NULL; - int just_cloned; - struct submodule_update_strategy update_strategy = { .type = SM_UPDATE_CHECKOUT }; - - if (argc < 3 || argc > 4) - die("submodule--helper update-module-clone expects <just-cloned> <path> [<update>]"); - - just_cloned = git_config_int("just_cloned", argv[1]); - path = argv[2]; - - if (argc == 4) - update = argv[3]; - - determine_submodule_update_strategy(the_repository, - just_cloned, path, update, - &update_strategy); - fputs(submodule_strategy_to_string(&update_strategy), stdout); - - return 0; -} - struct update_clone_data { const struct submodule *sub; struct object_id oid; @@ -2020,6 +2000,7 @@ struct submodule_update_clone { int failed_clones_nr, failed_clones_alloc; int max_jobs; + unsigned int init; }; #define SUBMODULE_UPDATE_CLONE_INIT { \ .list = MODULE_LIST_INIT, \ @@ -2038,10 +2019,11 @@ struct update_data { struct object_id suboid; struct submodule_update_strategy update_strategy; int depth; - unsigned int force: 1; - unsigned int quiet: 1; - unsigned int nofetch: 1; - unsigned int just_cloned: 1; + unsigned int force; + unsigned int quiet; + unsigned int nofetch; + unsigned int just_cloned; + unsigned int remote; }; #define UPDATE_DATA_INIT { .update_strategy = SUBMODULE_UPDATE_STRATEGY_INIT } @@ -2475,6 +2457,16 @@ static int do_run_update_procedure(struct update_data *ud) return run_update_command(ud, subforce); } +/* + * NEEDSWORK: As we convert "git submodule update" to C, + * update_submodule2() will invoke more and more functions, making it + * difficult to preserve the function ordering without forward + * declarations. + * + * When the conversion is complete, this forward declaration will be + * unnecessary and should be removed. + */ +static int update_submodule2(struct update_data *update_data); static void update_submodule(struct update_clone_data *ucd) { fprintf(stdout, "dummy %s %d\t%s\n", @@ -2518,6 +2510,8 @@ static int update_clone(int argc, const char **argv, const char *prefix) int ret; struct option module_update_clone_options[] = { + OPT_BOOL(0, "init", &suc.init, + N_("initialize uninitialized submodules before update")), OPT_STRING(0, "prefix", &prefix, N_("path"), N_("path into the working tree")), @@ -2551,7 +2545,12 @@ static int update_clone(int argc, const char **argv, const char *prefix) }; const char *const git_submodule_helper_usage[] = { - N_("git submodule--helper update-clone [--prefix=<path>] [<path>...]"), + N_("git submodule [--quiet] update" + " [--init [--filter=<filter-spec>]] [--remote]" + " [-N|--no-fetch] [-f|--force]" + " [--checkout|--merge|--rebase]" + " [--[no-]recommend-shallow] [--reference <repository>]" + " [--recursive] [--[no-]single-branch] [--] [<path>...]"), NULL }; suc.prefix = prefix; @@ -2562,6 +2561,19 @@ static int update_clone(int argc, const char **argv, const char *prefix) memset(&filter_options, 0, sizeof(filter_options)); argc = parse_options(argc, argv, prefix, module_update_clone_options, git_submodule_helper_usage, 0); + + if (filter_options.choice && !suc.init) { + /* + * NEEDSWORK: Don't use usage_with_options() because the + * usage string is for "git submodule update", but the + * options are for "git submodule--helper update-clone". + * + * This will no longer be an issue when "update-clone" + * is replaced by "git submodule--helper update". + */ + usage(git_submodule_helper_usage[0]); + } + suc.filter_options = &filter_options; if (update) @@ -2576,6 +2588,29 @@ static int update_clone(int argc, const char **argv, const char *prefix) if (pathspec.nr) suc.warn_if_uninitialized = 1; + if (suc.init) { + struct module_list list = MODULE_LIST_INIT; + struct init_cb info = INIT_CB_INIT; + + if (module_list_compute(argc, argv, suc.prefix, + &pathspec, &list) < 0) + return 1; + + /* + * If there are no path args and submodule.active is set then, + * by default, only initialize 'active' modules. + */ + if (!argc && git_config_get_value_multi("submodule.active")) + module_list_active(&list); + + info.prefix = suc.prefix; + info.superprefix = suc.recursive_prefix; + if (suc.quiet) + info.flags |= OPT_QUIET; + + for_each_listed_submodule(&list, init_submodule_cb, &info); + } + ret = update_submodules(&suc); list_objects_filter_release(&filter_options); return ret; @@ -2583,16 +2618,17 @@ static int update_clone(int argc, const char **argv, const char *prefix) static int run_update_procedure(int argc, const char **argv, const char *prefix) { - int force = 0, quiet = 0, nofetch = 0, just_cloned = 0; char *prefixed_path, *update = NULL; struct update_data update_data = UPDATE_DATA_INIT; struct option options[] = { - OPT__QUIET(&quiet, N_("suppress output for update by rebase or merge")), - OPT__FORCE(&force, N_("force checkout updates"), 0), - OPT_BOOL('N', "no-fetch", &nofetch, + OPT__QUIET(&update_data.quiet, + N_("suppress output for update by rebase or merge")), + OPT__FORCE(&update_data.force, N_("force checkout updates"), + 0), + OPT_BOOL('N', "no-fetch", &update_data.nofetch, N_("don't fetch new objects from the remote site")), - OPT_BOOL(0, "just-cloned", &just_cloned, + OPT_BOOL(0, "just-cloned", &update_data.just_cloned, N_("overrides update mode in case the repository is a fresh clone")), OPT_INTEGER(0, "depth", &update_data.depth, N_("depth for shallow fetch")), OPT_STRING(0, "prefix", &prefix, @@ -2607,9 +2643,8 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix) OPT_CALLBACK_F(0, "oid", &update_data.oid, N_("sha1"), N_("SHA1 expected by superproject"), PARSE_OPT_NONEG, parse_opt_object_id), - OPT_CALLBACK_F(0, "suboid", &update_data.suboid, N_("subsha1"), - N_("SHA1 of submodule's HEAD"), PARSE_OPT_NONEG, - parse_opt_object_id), + OPT_BOOL(0, "remote", &update_data.remote, + N_("use SHA-1 of submodule's remote tracking branch")), OPT_END() }; @@ -2623,10 +2658,6 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix) if (argc != 1) usage_with_options(usage, options); - update_data.force = !!force; - update_data.quiet = !!quiet; - update_data.nofetch = !!nofetch; - update_data.just_cloned = !!just_cloned; update_data.sm_path = argv[0]; if (update_data.recursive_prefix) @@ -2641,11 +2672,7 @@ static int run_update_procedure(int argc, const char **argv, const char *prefix) &update_data.update_strategy); free(prefixed_path); - - if (!oideq(&update_data.oid, &update_data.suboid) || update_data.force) - return do_run_update_procedure(&update_data); - - return 3; + return update_submodule2(&update_data); } static int resolve_relative_path(int argc, const char **argv, const char *prefix) @@ -2697,23 +2724,6 @@ static const char *remote_submodule_branch(const char *path) return branch; } -static int resolve_remote_submodule_branch(int argc, const char **argv, - const char *prefix) -{ - const char *ret; - struct strbuf sb = STRBUF_INIT; - if (argc != 2) - die("submodule--helper remote-branch takes exactly one arguments, got %d", argc); - - ret = remote_submodule_branch(argv[1]); - if (!ret) - die("submodule %s doesn't exist", argv[1]); - - printf("%s", ret); - strbuf_release(&sb); - return 0; -} - static int push_check(int argc, const char **argv, const char *prefix) { struct remote *remote; @@ -2791,17 +2801,11 @@ static int push_check(int argc, const char **argv, const char *prefix) return 0; } -static int ensure_core_worktree(int argc, const char **argv, const char *prefix) +static void ensure_core_worktree(const char *path) { - const char *path; const char *cw; struct repository subrepo; - if (argc != 2) - BUG("submodule--helper ensure-core-worktree <path>"); - - path = argv[1]; - if (repo_submodule_init(&subrepo, the_repository, path, null_oid())) die(_("could not get a repository handle for submodule '%s'"), path); @@ -2821,8 +2825,6 @@ static int ensure_core_worktree(int argc, const char **argv, const char *prefix) free(abs_path); strbuf_release(&sb); } - - return 0; } static int absorb_git_dirs(int argc, const char **argv, const char *prefix) @@ -3045,6 +3047,42 @@ static int module_create_branch(int argc, const char **argv, const char *prefix) force, reflog, quiet, track, dry_run); return 0; } + +/* NEEDSWORK: this is a temporary name until we delete update_submodule() */ +static int update_submodule2(struct update_data *update_data) +{ + ensure_core_worktree(update_data->sm_path); + if (update_data->just_cloned) + oidcpy(&update_data->suboid, null_oid()); + else if (resolve_gitlink_ref(update_data->sm_path, "HEAD", &update_data->suboid)) + die(_("Unable to find current revision in submodule path '%s'"), + update_data->displaypath); + + if (update_data->remote) { + char *remote_name = get_default_remote_submodule(update_data->sm_path); + const char *branch = remote_submodule_branch(update_data->sm_path); + char *remote_ref = xstrfmt("refs/remotes/%s/%s", remote_name, branch); + + if (!update_data->nofetch) { + if (fetch_in_submodule(update_data->sm_path, update_data->depth, + 0, NULL)) + die(_("Unable to fetch in submodule path '%s'"), + update_data->sm_path); + } + + if (resolve_gitlink_ref(update_data->sm_path, remote_ref, &update_data->oid)) + die(_("Unable to find %s revision in submodule path '%s'"), + remote_ref, update_data->sm_path); + + free(remote_ref); + } + + if (!oideq(&update_data->oid, &update_data->suboid) || update_data->force) + return do_run_update_procedure(update_data); + + return 3; +} + struct add_data { const char *prefix; const char *branch; @@ -3433,20 +3471,16 @@ static struct cmd_struct commands[] = { {"name", module_name, 0}, {"clone", module_clone, 0}, {"add", module_add, SUPPORT_SUPER_PREFIX}, - {"update-module-mode", module_update_module_mode, 0}, {"update-clone", update_clone, 0}, {"run-update-procedure", run_update_procedure, 0}, - {"ensure-core-worktree", ensure_core_worktree, 0}, {"relative-path", resolve_relative_path, 0}, {"resolve-relative-url-test", resolve_relative_url_test, 0}, {"foreach", module_foreach, SUPPORT_SUPER_PREFIX}, {"init", module_init, SUPPORT_SUPER_PREFIX}, {"status", module_status, SUPPORT_SUPER_PREFIX}, - {"print-default-remote", print_default_remote, 0}, {"sync", module_sync, SUPPORT_SUPER_PREFIX}, {"deinit", module_deinit, 0}, {"summary", module_summary, SUPPORT_SUPER_PREFIX}, - {"remote-branch", resolve_remote_submodule_branch, 0}, {"push-check", push_check, 0}, {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX}, {"is-active", is_active, 0}, diff --git a/builtin/tag.c b/builtin/tag.c index 2479da0704..e5a8f85693 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -239,7 +239,7 @@ static int build_tag_object(struct strbuf *buf, int sign, struct object_id *resu { if (sign && do_sign(buf) < 0) return error(_("unable to sign the tag")); - if (write_object_file(buf->buf, buf->len, tag_type, result) < 0) + if (write_object_file(buf->buf, buf->len, OBJ_TAG, result) < 0) return error(_("unable to write tag file")); return 0; } diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 4a9466295b..dbeb0680a5 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -177,7 +177,7 @@ static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf) struct object_id oid; if (write_object_file(obj_buf->buffer, obj_buf->size, - type_name(obj->type), &oid) < 0) + obj->type, &oid) < 0) die("failed to write object %s", oid_to_hex(&obj->oid)); obj->flags |= FLAG_WRITTEN; } @@ -243,7 +243,7 @@ static void write_object(unsigned nr, enum object_type type, void *buf, unsigned long size) { if (!strict) { - if (write_object_file(buf, size, type_name(type), + if (write_object_file(buf, size, type, &obj_list[nr].oid) < 0) die("failed to write object"); added_object(nr, type, buf, size); @@ -251,7 +251,7 @@ static void write_object(unsigned nr, enum object_type type, obj_list[nr].obj = NULL; } else if (type == OBJ_BLOB) { struct blob *blob; - if (write_object_file(buf, size, type_name(type), + if (write_object_file(buf, size, type, &obj_list[nr].oid) < 0) die("failed to write object"); added_object(nr, type, buf, size); @@ -266,7 +266,7 @@ static void write_object(unsigned nr, enum object_type type, } else { struct object *obj; int eaten; - hash_object_file(the_hash_algo, buf, size, type_name(type), + hash_object_file(the_hash_algo, buf, size, type, &obj_list[nr].oid); added_object(nr, type, buf, size); obj = parse_object_buffer(the_repository, &obj_list[nr].oid, |