diff options
Diffstat (limited to 'builtin')
38 files changed, 734 insertions, 267 deletions
diff --git a/builtin/am.c b/builtin/am.c index 390b463144..3b61bd4c33 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -31,7 +31,7 @@ #include "preload-index.h" #include "sequencer.h" #include "revision.h" -#include "merge-recursive.h" +#include "merge-ort-wrappers.h" #include "log-tree.h" #include "notes-utils.h" #include "rerere.h" @@ -158,7 +158,7 @@ static void am_state_init(struct am_state *state) memset(state, 0, sizeof(*state)); - state->dir = git_pathdup("rebase-apply"); + state->dir = repo_git_path(the_repository, "rebase-apply"); state->prec = 4; @@ -1638,12 +1638,13 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa o.branch1 = "HEAD"; their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg); o.branch2 = their_tree_name; + o.ancestor = "constructed fake ancestor"; o.detect_directory_renames = MERGE_DIRECTORY_RENAMES_NONE; if (state->quiet) o.verbosity = 0; - if (merge_recursive_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { + if (merge_ort_generic(&o, &our_tree, &their_tree, 1, bases, &result)) { repo_rerere(the_repository, state->allow_rerere_autoupdate); free(their_tree_name); return error(_("Failed to merge in the changes.")); diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c index e30086c7d4..7f74bc702f 100644 --- a/builtin/checkout-index.c +++ b/builtin/checkout-index.c @@ -5,7 +5,6 @@ * */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -68,10 +67,10 @@ static void write_tempfile_record(const char *name, const char *prefix) } } -static int checkout_file(const char *name, const char *prefix) +static int checkout_file(struct index_state *index, const char *name, const char *prefix) { int namelen = strlen(name); - int pos = index_name_pos(the_repository->index, name, namelen); + int pos = index_name_pos(index, name, namelen); int has_same_name = 0; int is_file = 0; int is_skipped = 1; @@ -81,8 +80,8 @@ static int checkout_file(const char *name, const char *prefix) if (pos < 0) pos = -pos - 1; - while (pos <the_repository->index->cache_nr) { - struct cache_entry *ce =the_repository->index->cache[pos]; + while (pos < index->cache_nr) { + struct cache_entry *ce = index->cache[pos]; if (ce_namelen(ce) != namelen || memcmp(ce->name, name, namelen)) break; @@ -137,13 +136,13 @@ static int checkout_file(const char *name, const char *prefix) return -1; } -static int checkout_all(const char *prefix, int prefix_length) +static int checkout_all(struct index_state *index, const char *prefix, int prefix_length) { int i, errs = 0; struct cache_entry *last_ce = NULL; - for (i = 0; i < the_repository->index->cache_nr ; i++) { - struct cache_entry *ce = the_repository->index->cache[i]; + for (i = 0; i < index->cache_nr ; i++) { + struct cache_entry *ce = index->cache[i]; if (S_ISSPARSEDIR(ce->ce_mode)) { if (!ce_skip_worktree(ce)) @@ -156,8 +155,8 @@ static int checkout_all(const char *prefix, int prefix_length) * first entry inside the expanded sparse directory). */ if (ignore_skip_worktree) { - ensure_full_index(the_repository->index); - ce = the_repository->index->cache[i]; + ensure_full_index(index); + ce = index->cache[i]; } } @@ -213,7 +212,7 @@ static int option_parse_stage(const struct option *opt, int cmd_checkout_index(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i; struct lock_file lock_file = LOCK_INIT; @@ -253,19 +252,19 @@ int cmd_checkout_index(int argc, show_usage_with_options_if_asked(argc, argv, builtin_checkout_index_usage, builtin_checkout_index_options); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); prefix_length = prefix ? strlen(prefix) : 0; - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; - if (repo_read_index(the_repository) < 0) { + if (repo_read_index(repo) < 0) { die("invalid cache"); } argc = parse_options(argc, argv, prefix, builtin_checkout_index_options, builtin_checkout_index_usage, 0); - state.istate = the_repository->index; + state.istate = repo->index; state.force = force; state.quiet = quiet; state.not_new = not_new; @@ -285,8 +284,8 @@ int cmd_checkout_index(int argc, */ if (index_opt && !state.base_dir_len && !to_tempfile) { state.refresh_cache = 1; - state.istate = the_repository->index; - repo_hold_locked_index(the_repository, &lock_file, + state.istate = repo->index; + repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR); } @@ -304,7 +303,7 @@ int cmd_checkout_index(int argc, if (read_from_stdin) die("git checkout-index: don't mix '--stdin' and explicit filenames"); p = prefix_path(prefix, prefix_length, arg); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } @@ -326,7 +325,7 @@ int cmd_checkout_index(int argc, strbuf_swap(&buf, &unquoted); } p = prefix_path(prefix, prefix_length, buf.buf); - err |= checkout_file(p, prefix); + err |= checkout_file(repo->index, p, prefix); free(p); } strbuf_release(&unquoted); @@ -334,7 +333,7 @@ int cmd_checkout_index(int argc, } if (all) - err |= checkout_all(prefix, prefix_length); + err |= checkout_all(repo->index, prefix, prefix_length); if (pc_workers > 1) err |= run_parallel_checkout(&state, pc_workers, pc_threshold, @@ -344,7 +343,7 @@ int cmd_checkout_index(int argc, return 1; if (is_lock_file_locked(&lock_file) && - write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK)) + write_locked_index(repo->index, &lock_file, COMMIT_LOCK)) die("Unable to write new index file"); return 0; } diff --git a/builtin/clone.c b/builtin/clone.c index f9a2ecbe9c..88276e5b7a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -342,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest, strbuf_setlen(src, src_len); die(_("failed to iterate over '%s'"), src->buf); } + + dir_iterator_free(iter); } static void clone_local(const char *src_repo, const char *dest_repo) @@ -835,7 +837,7 @@ static void write_refspec_config(const char *src_ref_prefix, static void dissociate_from_references(void) { - char *alternates = git_pathdup("objects/info/alternates"); + char *alternates = repo_git_path(the_repository, "objects/info/alternates"); if (!access(alternates, F_OK)) { struct child_process cmd = CHILD_PROCESS_INIT; @@ -1219,7 +1221,7 @@ int cmd_clone(int argc, strbuf_reset(&buf); strbuf_addf(&buf, "%s/refs", git_dir); - safe_create_dir(buf.buf, 1); + safe_create_dir(the_repository, buf.buf, 1); /* * additional config can be injected with -c, make sure it's included diff --git a/builtin/commit.c b/builtin/commit.c index 9fb405dd4a..2f45968222 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix, struct pathspec pathspec; int refresh_flags = REFRESH_QUIET; const char *ret; + char *path = NULL; if (is_status) refresh_flags |= REFRESH_UNMERGED; @@ -524,9 +525,9 @@ static const char *prepare_index(const char **argv, const char *prefix, if (write_locked_index(the_repository->index, &index_lock, 0)) die(_("unable to write new index file")); - hold_lock_file_for_update(&false_lock, - git_path("next-index-%"PRIuMAX, - (uintmax_t) getpid()), + path = repo_git_path(the_repository, "next-index-%"PRIuMAX, + (uintmax_t) getpid()); + hold_lock_file_for_update(&false_lock, path, LOCK_DIE_ON_ERROR); create_base_index(current_head); @@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix, out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); + free(path); return ret; } diff --git a/builtin/config.c b/builtin/config.c index 16e6e30555..53a90094e3 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -775,13 +775,13 @@ static void location_options_init(struct config_location_options *opts, opts->source.file = opts->file_to_free = git_system_config(); opts->source.scope = CONFIG_SCOPE_SYSTEM; } else if (opts->use_local_config) { - opts->source.file = opts->file_to_free = git_pathdup("config"); + opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; } else if (opts->use_worktree_config) { struct worktree **worktrees = get_worktrees(); if (the_repository->repository_format_worktree_config) opts->source.file = opts->file_to_free = - git_pathdup("config.worktree"); + repo_git_path(the_repository, "config.worktree"); else if (worktrees[0] && worktrees[1]) die(_("--worktree cannot be used with multiple " "working trees unless the config\n" @@ -790,7 +790,7 @@ static void location_options_init(struct config_location_options *opts, "section in \"git help worktree\" for details")); else opts->source.file = opts->file_to_free = - git_pathdup("config"); + repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; free_worktrees(worktrees); } else if (opts->source.file) { @@ -1087,7 +1087,7 @@ static int show_editor(struct config_location_options *opts) git_config(git_default_config, NULL); config_file = opts->source.file ? xstrdup(opts->source.file) : - git_pathdup("config"); + repo_git_path(the_repository, "config"); if (opts->use_global_config) { int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd >= 0) { diff --git a/builtin/diff-pairs.c b/builtin/diff-pairs.c new file mode 100644 index 0000000000..71c045331a --- /dev/null +++ b/builtin/diff-pairs.c @@ -0,0 +1,207 @@ +#include "builtin.h" +#include "config.h" +#include "diff.h" +#include "diffcore.h" +#include "gettext.h" +#include "hash.h" +#include "hex.h" +#include "object.h" +#include "parse-options.h" +#include "revision.h" +#include "strbuf.h" + +static unsigned parse_mode_or_die(const char *mode, const char **end) +{ + uint16_t ret; + + *end = parse_mode(mode, &ret); + if (!*end) + die(_("unable to parse mode: %s"), mode); + return ret; +} + +static void parse_oid_or_die(const char *hex, struct object_id *oid, + const char **end, const struct git_hash_algo *algop) +{ + if (parse_oid_hex_algop(hex, oid, end, algop) || *(*end)++ != ' ') + die(_("unable to parse object id: %s"), hex); +} + +int cmd_diff_pairs(int argc, const char **argv, const char *prefix, + struct repository *repo) +{ + struct strbuf path_dst = STRBUF_INIT; + struct strbuf path = STRBUF_INIT; + struct strbuf meta = STRBUF_INIT; + struct option *parseopts; + struct rev_info revs; + int line_term = '\0'; + int ret; + + const char * const builtin_diff_pairs_usage[] = { + N_("git diff-pairs -z [<diff-options>]"), + NULL + }; + struct option builtin_diff_pairs_options[] = { + OPT_END() + }; + + repo_init_revisions(repo, &revs, prefix); + + /* + * Diff options are usually parsed implicitly as part of + * setup_revisions(). Explicitly handle parsing to ensure options are + * printed in the usage message. + */ + parseopts = add_diff_options(builtin_diff_pairs_options, &revs.diffopt); + show_usage_with_options_if_asked(argc, argv, builtin_diff_pairs_usage, parseopts); + + repo_config(repo, git_diff_basic_config, NULL); + revs.diffopt.no_free = 1; + revs.disable_stdin = 1; + revs.abbrev = 0; + revs.diff = 1; + + argc = parse_options(argc, argv, prefix, parseopts, builtin_diff_pairs_usage, + PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_DASHDASH); + + if (setup_revisions(argc, argv, &revs, NULL) > 1) + usagef(_("unrecognized argument: %s"), argv[0]); + + /* + * With the -z option, both command input and raw output are + * NUL-delimited (this mode does not affect patch output). At present + * only NUL-delimited raw diff formatted input is supported. + */ + if (revs.diffopt.line_termination) + usage(_("working without -z is not supported")); + + if (revs.prune_data.nr) + usage(_("pathspec arguments not supported")); + + if (revs.pending.nr || revs.max_count != -1 || + revs.min_age != (timestamp_t)-1 || + revs.max_age != (timestamp_t)-1) + usage(_("revision arguments not allowed")); + + if (!revs.diffopt.output_format) + revs.diffopt.output_format = DIFF_FORMAT_PATCH; + + /* + * If rename detection is not requested, use rename information from the + * raw diff formatted input. Setting skip_resolving_statuses ensures + * diffcore_std() does not mess with rename information already present + * in queued filepairs. + */ + if (!revs.diffopt.detect_rename) + revs.diffopt.skip_resolving_statuses = 1; + + while (1) { + struct object_id oid_a, oid_b; + struct diff_filepair *pair; + unsigned mode_a, mode_b; + const char *p; + char status; + + if (strbuf_getwholeline(&meta, stdin, line_term) == EOF) + break; + + p = meta.buf; + if (!*p) { + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + /* + * When the diff queue is explicitly flushed, append a + * NUL byte to separate batches of diffs. + */ + fputc('\0', revs.diffopt.file); + fflush(revs.diffopt.file); + continue; + } + + if (*p != ':') + die(_("invalid raw diff input")); + p++; + + mode_a = parse_mode_or_die(p, &p); + mode_b = parse_mode_or_die(p, &p); + + if (S_ISDIR(mode_a) || S_ISDIR(mode_b)) + die(_("tree objects not supported")); + + parse_oid_or_die(p, &oid_a, &p, repo->hash_algo); + parse_oid_or_die(p, &oid_b, &p, repo->hash_algo); + + status = *p++; + + if (strbuf_getwholeline(&path, stdin, line_term) == EOF) + die(_("got EOF while reading path")); + + switch (status) { + case DIFF_STATUS_ADDED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '+', mode_b, + &oid_b, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_DELETED: + pair = diff_queue_addremove(&diff_queued_diff, + &revs.diffopt, '-', mode_a, + &oid_a, 1, path.buf, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_TYPE_CHANGED: + case DIFF_STATUS_MODIFIED: + pair = diff_queue_change(&diff_queued_diff, &revs.diffopt, + mode_a, mode_b, &oid_a, &oid_b, + 1, 1, path.buf, 0, 0); + if (pair) + pair->status = status; + break; + + case DIFF_STATUS_RENAMED: + case DIFF_STATUS_COPIED: { + struct diff_filespec *a, *b; + unsigned int score; + + if (strbuf_getwholeline(&path_dst, stdin, line_term) == EOF) + die(_("got EOF while reading destination path")); + + a = alloc_filespec(path.buf); + b = alloc_filespec(path_dst.buf); + fill_filespec(a, &oid_a, 1, mode_a); + fill_filespec(b, &oid_b, 1, mode_b); + + pair = diff_queue(&diff_queued_diff, a, b); + + if (strtoul_ui(p, 10, &score)) + die(_("unable to parse rename/copy score: %s"), p); + + pair->score = score * MAX_SCORE / 100; + pair->status = status; + pair->renamed_pair = 1; + } + break; + + default: + die(_("unknown diff status: %c"), status); + } + } + + revs.diffopt.no_free = 0; + diffcore_std(&revs.diffopt); + diff_flush(&revs.diffopt); + ret = diff_result_code(&revs); + + strbuf_release(&path_dst); + strbuf_release(&path); + strbuf_release(&meta); + release_revisions(&revs); + FREE_AND_NULL(parseopts); + + return ret; +} diff --git a/builtin/fast-export.c b/builtin/fast-export.c index a5c82eef1d..126980f724 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -35,8 +35,11 @@ static const char *fast_export_usage[] = { NULL }; +enum sign_mode { SIGN_ABORT, SIGN_VERBATIM, SIGN_STRIP, SIGN_WARN_VERBATIM, SIGN_WARN_STRIP }; + static int progress; -static enum signed_tag_mode { SIGNED_TAG_ABORT, VERBATIM, WARN, WARN_STRIP, STRIP } signed_tag_mode = SIGNED_TAG_ABORT; +static enum sign_mode signed_tag_mode = SIGN_ABORT; +static enum sign_mode signed_commit_mode = SIGN_ABORT; static enum tag_of_filtered_mode { TAG_FILTERING_ABORT, DROP, REWRITE } tag_of_filtered_mode = TAG_FILTERING_ABORT; static enum reencode_mode { REENCODE_ABORT, REENCODE_YES, REENCODE_NO } reencode_mode = REENCODE_ABORT; static int fake_missing_tagger; @@ -53,23 +56,24 @@ static int anonymize; static struct hashmap anonymized_seeds; static struct revision_sources revision_sources; -static int parse_opt_signed_tag_mode(const struct option *opt, +static int parse_opt_sign_mode(const struct option *opt, const char *arg, int unset) { - enum signed_tag_mode *val = opt->value; - - if (unset || !strcmp(arg, "abort")) - *val = SIGNED_TAG_ABORT; + enum sign_mode *val = opt->value; + if (unset) + return 0; + else if (!strcmp(arg, "abort")) + *val = SIGN_ABORT; else if (!strcmp(arg, "verbatim") || !strcmp(arg, "ignore")) - *val = VERBATIM; - else if (!strcmp(arg, "warn")) - *val = WARN; + *val = SIGN_VERBATIM; + else if (!strcmp(arg, "warn-verbatim") || !strcmp(arg, "warn")) + *val = SIGN_WARN_VERBATIM; else if (!strcmp(arg, "warn-strip")) - *val = WARN_STRIP; + *val = SIGN_WARN_STRIP; else if (!strcmp(arg, "strip")) - *val = STRIP; + *val = SIGN_STRIP; else - return error("Unknown signed-tags mode: %s", arg); + return error("Unknown %s mode: %s", opt->long_name, arg); return 0; } @@ -510,21 +514,6 @@ static void show_filemodify(struct diff_queue_struct *q, } } -static const char *find_encoding(const char *begin, const char *end) -{ - const char *needle = "\nencoding "; - char *bol, *eol; - - bol = memmem(begin, end ? end - begin : strlen(begin), - needle, strlen(needle)); - if (!bol) - return NULL; - bol += strlen(needle); - eol = strchrnul(bol, '\n'); - *eol = '\0'; - return bol; -} - static char *anonymize_ref_component(void) { static int counter; @@ -626,13 +615,53 @@ static void anonymize_ident_line(const char **beg, const char **end) *end = out->buf + out->len; } +/* + * find_commit_multiline_header is similar to find_commit_header, + * except that it handles multi-line headers, rather than simply + * returning the first line of the header. + * + * The returned string has had the ' ' line continuation markers + * removed, and points to allocated memory that must be free()d (not + * to memory within 'msg'). + * + * If the header is found, then *end is set to point at the '\n' in + * msg that immediately follows the header value. + */ +static const char *find_commit_multiline_header(const char *msg, + const char *key, + const char **end) +{ + struct strbuf val = STRBUF_INIT; + const char *bol, *eol; + size_t len; + + bol = find_commit_header(msg, key, &len); + if (!bol) + return NULL; + eol = bol + len; + strbuf_add(&val, bol, len); + + while (eol[0] == '\n' && eol[1] == ' ') { + bol = eol + 2; + eol = strchrnul(bol, '\n'); + strbuf_addch(&val, '\n'); + strbuf_add(&val, bol, eol - bol); + } + + *end = eol; + return strbuf_detach(&val, NULL); +} + static void handle_commit(struct commit *commit, struct rev_info *rev, struct string_list *paths_of_changed_objects) { int saved_output_format = rev->diffopt.output_format; - const char *commit_buffer; + const char *commit_buffer, *commit_buffer_cursor; const char *author, *author_end, *committer, *committer_end; - const char *encoding, *message; + const char *encoding = NULL; + size_t encoding_len; + const char *signature_alg = NULL, *signature = NULL; + const char *message; char *reencoded = NULL; struct commit_list *p; const char *refname; @@ -641,21 +670,43 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, rev->diffopt.output_format = DIFF_FORMAT_CALLBACK; parse_commit_or_die(commit); - commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); - author = strstr(commit_buffer, "\nauthor "); + commit_buffer_cursor = commit_buffer = repo_get_commit_buffer(the_repository, commit, NULL); + + author = strstr(commit_buffer_cursor, "\nauthor "); if (!author) die("could not find author in commit %s", oid_to_hex(&commit->object.oid)); author++; - author_end = strchrnul(author, '\n'); - committer = strstr(author_end, "\ncommitter "); + commit_buffer_cursor = author_end = strchrnul(author, '\n'); + + committer = strstr(commit_buffer_cursor, "\ncommitter "); if (!committer) die("could not find committer in commit %s", oid_to_hex(&commit->object.oid)); committer++; - committer_end = strchrnul(committer, '\n'); - message = strstr(committer_end, "\n\n"); - encoding = find_encoding(committer_end, message); + commit_buffer_cursor = committer_end = strchrnul(committer, '\n'); + + /* + * find_commit_header() and find_commit_multiline_header() get + * a `+ 1` because commit_buffer_cursor points at the trailing + * "\n" at the end of the previous line, but they want a + * pointer to the beginning of the next line. + */ + + if (*commit_buffer_cursor == '\n') { + encoding = find_commit_header(commit_buffer_cursor + 1, "encoding", &encoding_len); + if (encoding) + commit_buffer_cursor = encoding + encoding_len; + } + + if (*commit_buffer_cursor == '\n') { + if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig", &commit_buffer_cursor))) + signature_alg = "sha1"; + else if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig-sha256", &commit_buffer_cursor))) + signature_alg = "sha256"; + } + + message = strstr(commit_buffer_cursor, "\n\n"); if (message) message += 2; @@ -694,16 +745,20 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, if (anonymize) { reencoded = anonymize_commit_message(); } else if (encoding) { - switch(reencode_mode) { + char *buf; + switch (reencode_mode) { case REENCODE_YES: - reencoded = reencode_string(message, "UTF-8", encoding); + buf = xstrfmt("%.*s", (int)encoding_len, encoding); + reencoded = reencode_string(message, "UTF-8", buf); + free(buf); break; case REENCODE_NO: break; case REENCODE_ABORT: - die("Encountered commit-specific encoding %s in commit " + die("Encountered commit-specific encoding %.*s in commit " "%s; use --reencode=[yes|no] to handle it", - encoding, oid_to_hex(&commit->object.oid)); + (int)encoding_len, encoding, + oid_to_hex(&commit->object.oid)); } } if (!commit->parents) @@ -714,8 +769,33 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, printf("%.*s\n%.*s\n", (int)(author_end - author), author, (int)(committer_end - committer), committer); + if (signature) { + switch (signed_commit_mode) { + case SIGN_ABORT: + die("encountered signed commit %s; use " + "--signed-commits=<mode> to handle it", + oid_to_hex(&commit->object.oid)); + case SIGN_WARN_VERBATIM: + warning("exporting signed commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_VERBATIM: + printf("gpgsig %s\ndata %u\n%s", + signature_alg, + (unsigned)strlen(signature), + signature); + break; + case SIGN_WARN_STRIP: + warning("stripping signature from commit %s", + oid_to_hex(&commit->object.oid)); + /* fallthru */ + case SIGN_STRIP: + break; + } + free((char *)signature); + } if (!reencoded && encoding) - printf("encoding %s\n", encoding); + printf("encoding %.*s\n", (int)encoding_len, encoding); printf("data %u\n%s", (unsigned)(reencoded ? strlen(reencoded) : message @@ -828,22 +908,22 @@ static void handle_tag(const char *name, struct tag *tag) const char *signature = strstr(message, "\n-----BEGIN PGP SIGNATURE-----\n"); if (signature) - switch(signed_tag_mode) { - case SIGNED_TAG_ABORT: + switch (signed_tag_mode) { + case SIGN_ABORT: die("encountered signed tag %s; use " "--signed-tags=<mode> to handle it", oid_to_hex(&tag->object.oid)); - case WARN: + case SIGN_WARN_VERBATIM: warning("exporting signed tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case VERBATIM: + case SIGN_VERBATIM: break; - case WARN_STRIP: + case SIGN_WARN_STRIP: warning("stripping signature from tag %s", oid_to_hex(&tag->object.oid)); /* fallthru */ - case STRIP: + case SIGN_STRIP: message_size = signature + 1 - message; break; } @@ -853,7 +933,7 @@ static void handle_tag(const char *name, struct tag *tag) tagged = tag->tagged; tagged_mark = get_object_mark(tagged); if (!tagged_mark) { - switch(tag_of_filtered_mode) { + switch (tag_of_filtered_mode) { case TAG_FILTERING_ABORT: die("tag %s tags unexported object; use " "--tag-of-filtered-object=<mode> to handle it", @@ -965,7 +1045,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) continue; } - switch(commit->object.type) { + switch (commit->object.type) { case OBJ_COMMIT: break; case OBJ_BLOB: @@ -1189,6 +1269,7 @@ int cmd_fast_export(int argc, const char *prefix, struct repository *repo UNUSED) { + const char *env_signed_commits_noabort; struct rev_info revs; struct commit *commit; char *export_filename = NULL, @@ -1202,7 +1283,10 @@ int cmd_fast_export(int argc, N_("show progress after <n> objects")), OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"), N_("select handling of signed tags"), - parse_opt_signed_tag_mode), + parse_opt_sign_mode), + OPT_CALLBACK(0, "signed-commits", &signed_commit_mode, N_("mode"), + N_("select handling of signed commits"), + parse_opt_sign_mode), OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"), N_("select handling of tags that tag filtered objects"), parse_opt_tag_of_filtered_mode), @@ -1243,6 +1327,10 @@ int cmd_fast_export(int argc, if (argc == 1) usage_with_options (fast_export_usage, options); + env_signed_commits_noabort = getenv("FAST_EXPORT_SIGNED_COMMITS_NOABORT"); + if (env_signed_commits_noabort && *env_signed_commits_noabort) + signed_commit_mode = SIGN_WARN_STRIP; + /* we handle encodings */ git_config(git_default_config, NULL); diff --git a/builtin/fast-import.c b/builtin/fast-import.c index d6a368a566..e432e8d5a1 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -328,7 +328,7 @@ static void write_branch_report(FILE *rpt, struct branch *b) static void write_crash_report(const char *err) { - char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); + char *loc = repo_git_path(the_repository, "fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); FILE *rpt = fopen(loc, "w"); struct branch *b; unsigned long lu; @@ -2719,10 +2719,13 @@ static struct hash_list *parse_merge(unsigned int *count) static void parse_new_commit(const char *arg) { + static struct strbuf sig = STRBUF_INIT; static struct strbuf msg = STRBUF_INIT; + struct string_list siglines = STRING_LIST_INIT_NODUP; struct branch *b; char *author = NULL; char *committer = NULL; + char *sig_alg = NULL; char *encoding = NULL; struct hash_list *merge_list = NULL; unsigned int merge_count; @@ -2746,6 +2749,13 @@ static void parse_new_commit(const char *arg) } if (!committer) die("Expected committer but didn't get one"); + if (skip_prefix(command_buf.buf, "gpgsig ", &v)) { + sig_alg = xstrdup(v); + read_next_command(); + parse_data(&sig, 0, NULL); + read_next_command(); + } else + strbuf_setlen(&sig, 0); if (skip_prefix(command_buf.buf, "encoding ", &v)) { encoding = xstrdup(v); read_next_command(); @@ -2819,10 +2829,23 @@ static void parse_new_commit(const char *arg) strbuf_addf(&new_data, "encoding %s\n", encoding); + if (sig_alg) { + if (!strcmp(sig_alg, "sha1")) + strbuf_addstr(&new_data, "gpgsig "); + else if (!strcmp(sig_alg, "sha256")) + strbuf_addstr(&new_data, "gpgsig-sha256 "); + else + die("Expected gpgsig algorithm sha1 or sha256, got %s", sig_alg); + string_list_split_in_place(&siglines, sig.buf, "\n", -1); + strbuf_add_separated_string_list(&new_data, "\n ", &siglines); + strbuf_addch(&new_data, '\n'); + } strbuf_addch(&new_data, '\n'); strbuf_addbuf(&new_data, &msg); + string_list_clear(&siglines, 1); free(author); free(committer); + free(sig_alg); free(encoding); if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark)) @@ -3280,7 +3303,7 @@ static char* make_fast_import_path(const char *path) { if (!relative_marks_paths || is_absolute_path(path)) return prefix_filename(global_prefix, path); - return git_pathdup("info/fast-import/%s", path); + return repo_git_path(the_repository, "info/fast-import/%s", path); } static void option_import_marks(const char *marks, diff --git a/builtin/fetch.c b/builtin/fetch.c index 1c740d5aac..9830c09011 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -586,7 +586,7 @@ static struct ref *get_ref_map(struct remote *remote, struct refspec_item tag_refspec; /* also fetch all tags */ - refspec_item_init(&tag_refspec, TAG_REFSPEC, 0); + refspec_item_init_push(&tag_refspec, TAG_REFSPEC); get_fetch_map(remote_refs, &tag_refspec, &tail, 0); refspec_item_clear(&tag_refspec); } else if (tags == TAGS_DEFAULT && *autotags) { @@ -1718,7 +1718,6 @@ static int do_fetch(struct transport *transport, const struct ref *remote_refs; struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; - int must_list_refs = 1; struct fetch_head fetch_head = { 0 }; struct strbuf err = STRBUF_INIT; @@ -1737,21 +1736,7 @@ static int do_fetch(struct transport *transport, } if (rs->nr) { - int i; - refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes); - - /* - * We can avoid listing refs if all of them are exact - * OIDs - */ - must_list_refs = 0; - for (i = 0; i < rs->nr; i++) { - if (!rs->items[i].exact_sha1) { - must_list_refs = 1; - break; - } - } } else { struct branch *branch = branch_get(NULL); @@ -1766,21 +1751,30 @@ static int do_fetch(struct transport *transport, branch->merge[i]->src); } } - } - if (tags == TAGS_SET || tags == TAGS_DEFAULT) { - must_list_refs = 1; - if (transport_ls_refs_options.ref_prefixes.nr) + /* + * If there are no refs specified to fetch, then we just + * fetch HEAD; mention that to narrow the advertisement. + */ + if (!transport_ls_refs_options.ref_prefixes.nr) strvec_push(&transport_ls_refs_options.ref_prefixes, - "refs/tags/"); + "HEAD"); } - if (uses_remote_tracking(transport, rs)) { - must_list_refs = 1; - strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD"); - } + if (tags == TAGS_SET || tags == TAGS_DEFAULT) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "refs/tags/"); - if (must_list_refs) { + if (transport_ls_refs_options.ref_prefixes.nr && + uses_remote_tracking(transport, rs)) + strvec_push(&transport_ls_refs_options.ref_prefixes, + "HEAD"); + + /* + * Only initiate ref listing if we have at least one ref we want to + * know about. + */ + if (transport_ls_refs_options.ref_prefixes.nr) { trace2_region_enter("fetch", "remote_refs", the_repository); remote_refs = transport_get_remote_refs(transport, &transport_ls_refs_options); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 8085ebd8fe..3d2207ec77 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "commit.h" #include "config.h" @@ -20,7 +19,7 @@ static char const * const for_each_ref_usage[] = { int cmd_for_each_ref(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_sorting *sorting; struct string_list sorting_options = STRING_LIST_INIT_DUP; @@ -63,7 +62,7 @@ int cmd_for_each_ref(int argc, format.format = "%(objectname) %(objecttype)\t%(refname)"; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); /* Set default (refname) sorting */ string_list_append(&sorting_options, "refname"); diff --git a/builtin/fsck.c b/builtin/fsck.c index 7a4dcb0716..8fbd1d6334 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -50,6 +50,7 @@ static int verbose; static int show_progress = -1; static int show_dangling = 1; static int name_objects; +static int check_references = 1; #define ERROR_OBJECT 01 #define ERROR_REACHABLE 02 #define ERROR_PACK 04 @@ -326,7 +327,7 @@ static void check_unreachable_object(struct object *obj) printable_type(&obj->oid, obj->type), describe_object(&obj->oid)); if (write_lost_and_found) { - char *filename = git_pathdup("lost-found/%s/%s", + char *filename = repo_git_path(the_repository, "lost-found/%s/%s", obj->type == OBJ_COMMIT ? "commit" : "other", describe_object(&obj->oid)); FILE *f; @@ -905,11 +906,37 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress) return res; } +static void fsck_refs(struct repository *r) +{ + struct child_process refs_verify = CHILD_PROCESS_INIT; + struct progress *progress = NULL; + + if (show_progress) + progress = start_progress(r, _("Checking ref database"), 1); + + if (verbose) + fprintf_ln(stderr, _("Checking ref database")); + + child_process_init(&refs_verify); + refs_verify.git_cmd = 1; + strvec_pushl(&refs_verify.args, "refs", "verify", NULL); + if (verbose) + strvec_push(&refs_verify.args, "--verbose"); + if (check_strict) + strvec_push(&refs_verify.args, "--strict"); + + if (run_command(&refs_verify)) + errors_found |= ERROR_REFS; + + display_progress(progress, 1); + stop_progress(&progress); +} + static char const * const fsck_usage[] = { N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n" " [--[no-]full] [--strict] [--verbose] [--lost-found]\n" " [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n" - " [--[no-]name-objects] [<object>...]"), + " [--[no-]name-objects] [--[no-]references] [<object>...]"), NULL }; @@ -928,6 +955,7 @@ static struct option fsck_opts[] = { N_("write dangling objects in .git/lost-found")), OPT_BOOL(0, "progress", &show_progress, N_("show progress")), OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")), + OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")), OPT_END(), }; @@ -970,6 +998,9 @@ int cmd_fsck(int argc, git_config(git_fsck_config, &fsck_obj_options); prepare_repo_settings(the_repository); + if (check_references) + fsck_refs(the_repository); + if (connectivity_only) { for_each_loose_object(mark_loose_for_connectivity, NULL, 0); for_each_packed_object(the_repository, @@ -1057,7 +1088,7 @@ int cmd_fsck(int argc, struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(the_repository); - char *path; + char *path, *wt_gitdir; /* * Make a copy since the buffer is reusable @@ -1065,9 +1096,13 @@ int cmd_fsck(int argc, * while we're examining the index. */ path = xstrdup(worktree_git_path(the_repository, wt, "index")); - read_index_from(&istate, path, get_worktree_git_dir(wt)); + wt_gitdir = get_worktree_git_dir(wt); + + read_index_from(&istate, path, wt_gitdir); fsck_index(&istate, path, wt->is_current); + discard_index(&istate); + free(wt_gitdir); free(path); } free_worktrees(worktrees); diff --git a/builtin/gc.c b/builtin/gc.c index 409d454a4b..99431fd467 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -99,9 +99,11 @@ static void process_log_file(void) /* There was some error recorded in the lock file */ commit_lock_file(&log_lock); } else { + char *path = repo_git_path(the_repository, "gc.log"); /* No error, clean up any old gc.log */ - unlink(git_path("gc.log")); + unlink(path); rollback_lock_file(&log_lock); + free(path); } } @@ -300,8 +302,11 @@ static int too_many_loose_objects(struct gc_config *cfg) int num_loose = 0; int needed = 0; const unsigned hexsz_loose = the_hash_algo->hexsz - 2; + char *path; - dir = opendir(git_path("objects/17")); + path = repo_git_path(the_repository, "objects/17"); + dir = opendir(path); + free(path); if (!dir) return 0; @@ -550,7 +555,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) if (xgethostname(my_host, sizeof(my_host))) xsnprintf(my_host, sizeof(my_host), "unknown"); - pidfile_path = git_pathdup("gc.pid"); + pidfile_path = repo_git_path(the_repository, "gc.pid"); fd = hold_lock_file_for_update(&lock, pidfile_path, LOCK_DIE_ON_ERROR); if (!force) { @@ -611,7 +616,7 @@ static int report_last_gc_error(void) int ret = 0; ssize_t len; struct stat st; - char *gc_log_path = git_pathdup("gc.log"); + char *gc_log_path = repo_git_path(the_repository, "gc.log"); if (stat(gc_log_path, &st)) { if (errno == ENOENT) @@ -826,11 +831,12 @@ struct repository *repo UNUSED) } if (daemonized) { - hold_lock_file_for_update(&log_lock, - git_path("gc.log"), + char *path = repo_git_path(the_repository, "gc.log"); + hold_lock_file_for_update(&log_lock, path, LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); atexit(process_log_file_at_exit); + free(path); } gc_before_repack(&opts, &cfg); @@ -892,8 +898,11 @@ struct repository *repo UNUSED) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); - if (!daemonized) - unlink(git_path("gc.log")); + if (!daemonized) { + char *path = repo_git_path(the_repository, "gc.log"); + unlink(path); + free(path); + } out: gc_config_release(&cfg); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 52cc97d52c..50573ba049 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1286,6 +1286,7 @@ static void parse_pack_objects(unsigned char *hash) /* Check pack integrity */ flush(); + the_hash_algo->init_fn(&tmp_ctx); git_hash_clone(&tmp_ctx, &input_ctx); git_hash_final(hash, &tmp_ctx); if (!hasheq(fill(the_hash_algo->rawsz), hash, the_repository->hash_algo)) diff --git a/builtin/init-db.c b/builtin/init-db.c index 096f96b9c4..196dccdd77 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -132,8 +132,8 @@ int cmd_init_db(int argc, * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@ -145,7 +145,7 @@ int cmd_init_db(int argc, die_errno(_("cannot mkdir %s"), argv[0]); break; } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@ -175,7 +175,7 @@ int cmd_init_db(int argc, } if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --git a/builtin/log.c b/builtin/log.c index e41f88945e..04a6ef97bc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -2309,8 +2309,8 @@ int cmd_format_patch(int argc, * We consider <outdir> as 'outside of gitdir', therefore avoid * applying adjust_shared_perm in s-c-l-d. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(output_directory)) { case SCLD_OK: case SCLD_EXISTS: @@ -2319,7 +2319,7 @@ int cmd_format_patch(int argc, die(_("could not create leading directories " "of '%s'"), output_directory); } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) die_errno(_("could not create directory '%s'"), output_directory); diff --git a/builtin/ls-files.c b/builtin/ls-files.c index a4431429b7..70a377e9c0 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -6,7 +6,6 @@ * Copyright (C) Linus Torvalds, 2005 */ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "builtin.h" @@ -245,12 +244,13 @@ static void show_submodule(struct repository *superproject, repo_clear(&subrepo); } -static void expand_objectsize(struct strbuf *line, const struct object_id *oid, +static void expand_objectsize(struct repository *repo, struct strbuf *line, + const struct object_id *oid, const enum object_type type, unsigned int padded) { if (type == OBJ_BLOB) { unsigned long size; - if (oid_object_info(the_repository, oid, &size) < 0) + if (oid_object_info(repo, oid, &size) < 0) die(_("could not get object info about '%s'"), oid_to_hex(oid)); if (padded) @@ -283,10 +283,10 @@ static void show_ce_fmt(struct repository *repo, const struct cache_entry *ce, else if (skip_prefix(format, "(objecttype)", &format)) strbuf_addstr(&sb, type_name(object_type(ce->ce_mode))); else if (skip_prefix(format, "(objectsize:padded)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 1); else if (skip_prefix(format, "(objectsize)", &format)) - expand_objectsize(&sb, &ce->oid, + expand_objectsize(repo, &sb, &ce->oid, object_type(ce->ce_mode), 0); else if (skip_prefix(format, "(stage)", &format)) strbuf_addf(&sb, "%d", ce_stage(ce)); @@ -348,7 +348,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir, } } -static void show_ru_info(struct index_state *istate) +static void show_ru_info(struct repository *repo, struct index_state *istate) { struct string_list_item *item; @@ -370,7 +370,7 @@ static void show_ru_info(struct index_state *istate) if (!ui->mode[i]) continue; printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i], - repo_find_unique_abbrev(the_repository, &ui->oid[i], abbrev), + repo_find_unique_abbrev(repo, &ui->oid[i], abbrev), i + 1); write_name(path); } @@ -567,7 +567,7 @@ static int option_parse_exclude_standard(const struct option *opt, int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix, - struct repository *repo UNUSED) + struct repository *repo) { int require_work_tree = 0, show_tag = 0, i; char *max_prefix; @@ -647,15 +647,15 @@ int cmd_ls_files(int argc, show_usage_with_options_if_asked(argc, argv, ls_files_usage, builtin_ls_files_options); - prepare_repo_settings(the_repository); - the_repository->settings.command_requires_full_index = 0; + prepare_repo_settings(repo); + repo->settings.command_requires_full_index = 0; prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); - if (repo_read_index(the_repository) < 0) + if (repo_read_index(repo) < 0) die("index file corrupt"); argc = parse_options(argc, argv, prefix, builtin_ls_files_options, @@ -724,7 +724,7 @@ int cmd_ls_files(int argc, max_prefix = common_prefix(&pathspec); max_prefix_len = get_common_prefix_len(max_prefix); - prune_index(the_repository->index, max_prefix, max_prefix_len); + prune_index(repo->index, max_prefix, max_prefix_len); /* Treat unmatching pathspec elements as errors */ if (pathspec.nr && error_unmatch) @@ -748,13 +748,13 @@ int cmd_ls_files(int argc, */ if (show_stage || show_unmerged) die(_("options '%s' and '%s' cannot be used together"), "ls-files --with-tree", "-s/-u"); - overlay_tree_on_index(the_repository->index, with_tree, max_prefix); + overlay_tree_on_index(repo->index, with_tree, max_prefix); } - show_files(the_repository, &dir); + show_files(repo, &dir); if (show_resolve_undo) - show_ru_info(the_repository->index); + show_ru_info(repo, repo->index); if (ps_matched && report_path_error(ps_matched, &pathspec)) { fprintf(stderr, "Did you forget to 'git add'?\n"); diff --git a/builtin/name-rev.c b/builtin/name-rev.c index beac166b5c..65f867d7a4 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -567,7 +567,11 @@ int cmd_name_rev(int argc, { struct mem_pool string_pool; struct object_array revs = OBJECT_ARRAY_INIT; - int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0; + +#ifndef WITH_BREAKING_CHANGES + int transform_stdin = 0; +#endif + int all = 0, annotate_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0; struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP }; struct option opts[] = { OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")), @@ -578,11 +582,13 @@ int cmd_name_rev(int argc, N_("ignore refs matching <pattern>")), OPT_GROUP(""), OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")), +#ifndef WITH_BREAKING_CHANGES OPT_BOOL_F(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead"), PARSE_OPT_HIDDEN), +#endif /* WITH_BREAKING_CHANGES */ OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")), OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")), OPT_BOOL(0, "always", &always, @@ -597,12 +603,14 @@ int cmd_name_rev(int argc, git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0); +#ifndef WITH_BREAKING_CHANGES if (transform_stdin) { warning("--stdin is deprecated. Please use --annotate-stdin instead, " "which is functionally equivalent.\n" "This option will be removed in a future release."); annotate_stdin = 1; } +#endif if (all + annotate_stdin + !!argc > 1) { error("Specify either a list, or --all, not both!"); diff --git a/builtin/notes.c b/builtin/notes.c index d051abf6df..ff61ec5f2d 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -197,7 +197,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data * struct strbuf buf = STRBUF_INIT; /* write the template message before editing: */ - d->edit_path = git_pathdup("NOTES_EDITMSG"); + d->edit_path = repo_git_path(the_repository, "NOTES_EDITMSG"); fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (d->msg_nr) @@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix, else { /* Merge has unresolved conflicts */ struct worktree **worktrees; const struct worktree *wt; + char *path; + /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL, @@ -994,10 +996,13 @@ static int merge(int argc, const char **argv, const char *prefix, if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL)) die(_("failed to store link to current notes ref (%s)"), notes_ref); + + path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " "and commit the result with 'git notes merge --commit', " "or abort the merge with 'git notes merge --abort'.\n"), - git_path(NOTES_MERGE_WORKTREE)); + path); + free(path); } free_notes(t); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 58a9b16126..6b06d159d2 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -206,6 +206,7 @@ static int have_non_local_packs; static int incremental; static int ignore_packed_keep_on_disk; static int ignore_packed_keep_in_core; +static int ignore_packed_keep_in_core_has_cruft; static int allow_ofs_delta; static struct pack_idx_option pack_idx_opts; static const char *base_name; @@ -1397,7 +1398,8 @@ static void write_pack_file(void) if (write_bitmap_index) { bitmap_writer_init(&bitmap_writer, - the_repository, &to_pack); + the_repository, &to_pack, + NULL); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, written_list); @@ -1502,8 +1504,60 @@ static int have_duplicate_entry(const struct object_id *oid, return 1; } +static int want_cruft_object_mtime(struct repository *r, + const struct object_id *oid, + unsigned flags, uint32_t mtime) +{ + struct packed_git **cache; + + for (cache = kept_pack_cache(r, flags); *cache; cache++) { + struct packed_git *p = *cache; + off_t ofs; + uint32_t candidate_mtime; + + ofs = find_pack_entry_one(oid, p); + if (!ofs) + continue; + + /* + * We have a copy of the object 'oid' in a non-cruft + * pack. We can avoid packing an additional copy + * regardless of what the existing copy's mtime is since + * it is outside of a cruft pack. + */ + if (!p->is_cruft) + return 0; + + /* + * If we have a copy of the object 'oid' in a cruft + * pack, then either read the cruft pack's mtime for + * that object, or, if that can't be loaded, assume the + * pack's mtime itself. + */ + if (!load_pack_mtimes(p)) { + uint32_t pos; + if (offset_to_pack_pos(p, ofs, &pos) < 0) + continue; + candidate_mtime = nth_packed_mtime(p, pos); + } else { + candidate_mtime = p->mtime; + } + + /* + * We have a surviving copy of the object in a cruft + * pack whose mtime is greater than or equal to the one + * we are considering. We can thus avoid packing an + * additional copy of that object. + */ + if (mtime <= candidate_mtime) + return 0; + } + + return -1; +} + static int want_found_object(const struct object_id *oid, int exclude, - struct packed_git *p) + struct packed_git *p, uint32_t mtime) { if (exclude) return 1; @@ -1553,12 +1607,29 @@ static int want_found_object(const struct object_id *oid, int exclude, if (ignore_packed_keep_in_core) flags |= IN_CORE_KEEP_PACKS; - if (ignore_packed_keep_on_disk && p->pack_keep) - return 0; - if (ignore_packed_keep_in_core && p->pack_keep_in_core) - return 0; - if (has_object_kept_pack(p->repo, oid, flags)) - return 0; + /* + * If the object is in a pack that we want to ignore, *and* we + * don't have any cruft packs that are being retained, we can + * abort quickly. + */ + if (!ignore_packed_keep_in_core_has_cruft) { + if (ignore_packed_keep_on_disk && p->pack_keep) + return 0; + if (ignore_packed_keep_in_core && p->pack_keep_in_core) + return 0; + if (has_object_kept_pack(p->repo, oid, flags)) + return 0; + } else { + /* + * But if there is at least one cruft pack which + * is being kept, we only want to include the + * provided object if it has a strictly greater + * mtime than any existing cruft copy. + */ + if (!want_cruft_object_mtime(p->repo, oid, flags, + mtime)) + return 0; + } } /* @@ -1577,7 +1648,8 @@ static int want_object_in_pack_one(struct packed_git *p, const struct object_id *oid, int exclude, struct packed_git **found_pack, - off_t *found_offset) + off_t *found_offset, + uint32_t found_mtime) { off_t offset; @@ -1593,7 +1665,7 @@ static int want_object_in_pack_one(struct packed_git *p, *found_offset = offset; *found_pack = p; } - return want_found_object(oid, exclude, p); + return want_found_object(oid, exclude, p, found_mtime); } return -1; } @@ -1607,10 +1679,11 @@ static int want_object_in_pack_one(struct packed_git *p, * function finds if there is any pack that has the object and returns the pack * and its offset in these variables. */ -static int want_object_in_pack(const struct object_id *oid, - int exclude, - struct packed_git **found_pack, - off_t *found_offset) +static int want_object_in_pack_mtime(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset, + uint32_t found_mtime) { int want; struct list_head *pos; @@ -1625,7 +1698,8 @@ static int want_object_in_pack(const struct object_id *oid, * are present we will determine the answer right now. */ if (*found_pack) { - want = want_found_object(oid, exclude, *found_pack); + want = want_found_object(oid, exclude, *found_pack, + found_mtime); if (want != -1) return want; @@ -1636,7 +1710,7 @@ static int want_object_in_pack(const struct object_id *oid, for (m = get_multi_pack_index(the_repository); m; m = m->next) { struct pack_entry e; if (fill_midx_entry(the_repository, oid, &e, m)) { - want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); if (want != -1) return want; } @@ -1644,7 +1718,7 @@ static int want_object_in_pack(const struct object_id *oid, list_for_each(pos, get_packed_git_mru(the_repository)) { struct packed_git *p = list_entry(pos, struct packed_git, mru); - want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset); + want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime); if (!exclude && want > 0) list_move(&p->mru, get_packed_git_mru(the_repository)); @@ -1674,6 +1748,15 @@ static int want_object_in_pack(const struct object_id *oid, return 1; } +static inline int want_object_in_pack(const struct object_id *oid, + int exclude, + struct packed_git **found_pack, + off_t *found_offset) +{ + return want_object_in_pack_mtime(oid, exclude, found_pack, found_offset, + 0); +} + static struct object_entry *create_object_entry(const struct object_id *oid, enum object_type type, uint32_t hash, @@ -3606,7 +3689,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type entry->no_try_delta = no_try_delta(name); } } else { - if (!want_object_in_pack(oid, 0, &pack, &offset)) + if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime)) return; if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) { /* @@ -3680,6 +3763,8 @@ static void mark_pack_kept_in_core(struct string_list *packs, unsigned keep) struct packed_git *p = item->util; if (!p) die(_("could not find pack '%s'"), item->string); + if (p->is_cruft && keep) + ignore_packed_keep_in_core_has_cruft = 1; p->pack_keep_in_core = keep; } } diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c index 4fdd68880e..e47bae1c80 100644 --- a/builtin/pack-refs.c +++ b/builtin/pack-refs.c @@ -1,5 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE - #include "builtin.h" #include "config.h" #include "gettext.h" @@ -15,7 +13,7 @@ static char const * const pack_refs_usage[] = { int cmd_pack_refs(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct ref_exclusions excludes = REF_EXCLUSIONS_INIT; struct string_list included_refs = STRING_LIST_INIT_NODUP; @@ -39,7 +37,7 @@ int cmd_pack_refs(int argc, N_("references to exclude")), OPT_END(), }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0)) usage_with_options(pack_refs_usage, opts); @@ -52,7 +50,7 @@ int cmd_pack_refs(int argc, if (!pack_refs_opts.includes->nr) string_list_append(pack_refs_opts.includes, "refs/tags/*"); - ret = refs_pack_refs(get_main_ref_store(the_repository), &pack_refs_opts); + ret = refs_pack_refs(get_main_ref_store(repo), &pack_refs_opts); clear_ref_exclusions(&excludes); string_list_clear(&included_refs, 0); diff --git a/builtin/pull.c b/builtin/pull.c index 9c4a00620a..a1ebc6ad33 100644 --- a/builtin/pull.c +++ b/builtin/pull.c @@ -738,7 +738,8 @@ static const char *get_tracking_branch(const char *remote, const char *refspec) const char *spec_src; const char *merge_branch; - refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH); + if (!refspec_item_init_fetch(&spec, refspec)) + die(_("invalid refspec '%s'"), refspec); spec_src = spec.src; if (!*spec_src || !strcmp(spec_src, "HEAD")) spec_src = "HEAD"; diff --git a/builtin/rebase.c b/builtin/rebase.c index 6c9eaf3788..d4715ed35d 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts) return run_command(&am); } - rebased_patches = xstrdup(git_path("rebased-patches")); + rebased_patches = repo_git_path(the_repository, "rebased-patches"); format_patch.out = open(rebased_patches, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (format_patch.out < 0) { diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 129305700c..7b28fc9df6 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash, static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) { - const char *retval, *git_dir; + const char *retval; + char *git_dir; struct strvec env = STRVEC_INIT; int invoked_hook; @@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w retval = push_to_deploy(sha1, &env, worktree->path); strvec_clear(&env); + free(git_dir); return retval; } diff --git a/builtin/refs.c b/builtin/refs.c index c459507d51..998d2a2c1c 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -8,7 +8,7 @@ #include "worktree.h" #define REFS_MIGRATE_USAGE \ - N_("git refs migrate --ref-format=<format> [--dry-run]") + N_("git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]") #define REFS_VERIFY_USAGE \ N_("git refs verify [--strict] [--verbose]") @@ -91,7 +91,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, git_config(git_fsck_config, &fsck_refs_options); prepare_repo_settings(the_repository); - worktrees = get_worktrees(); + worktrees = get_worktrees_without_reading_head(); for (size_t i = 0; worktrees[i]; i++) ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), &fsck_refs_options, worktrees[i]); diff --git a/builtin/remote.c b/builtin/remote.c index 816d482340..1b7aad8838 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -644,9 +644,11 @@ static int migrate_file(struct remote *remote) git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); #ifndef WITH_BREAKING_CHANGES if (remote->origin == REMOTE_REMOTES) - unlink_or_warn(git_path("remotes/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) - unlink_or_warn(git_path("branches/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "branches/%s", remote->name)); #endif /* WITH_BREAKING_CHANGES */ strbuf_release(&buf); diff --git a/builtin/repack.c b/builtin/repack.c index 75e3752353..f3330ade7b 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -1022,29 +1022,13 @@ static int write_filtered_pack(const struct pack_objects_args *args, return finish_pack_objects_cmd(&cmd, names, local); } -static int existing_cruft_pack_cmp(const void *va, const void *vb) +static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size, + struct existing_packs *existing) { - struct packed_git *a = *(struct packed_git **)va; - struct packed_git *b = *(struct packed_git **)vb; - - if (a->pack_size < b->pack_size) - return -1; - if (a->pack_size > b->pack_size) - return 1; - return 0; -} - -static void collapse_small_cruft_packs(FILE *in, size_t max_size, - struct existing_packs *existing) -{ - struct packed_git **existing_cruft, *p; + struct packed_git *p; struct strbuf buf = STRBUF_INIT; - size_t total_size = 0; - size_t existing_cruft_nr = 0; size_t i; - ALLOC_ARRAY(existing_cruft, existing->cruft_packs.nr); - for (p = get_all_packs(the_repository); p; p = p->next) { if (!(p->is_cruft && p->pack_local)) continue; @@ -1056,24 +1040,7 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size, if (!string_list_has_string(&existing->cruft_packs, buf.buf)) continue; - if (existing_cruft_nr >= existing->cruft_packs.nr) - BUG("too many cruft packs (found %"PRIuMAX", but knew " - "of %"PRIuMAX")", - (uintmax_t)existing_cruft_nr + 1, - (uintmax_t)existing->cruft_packs.nr); - existing_cruft[existing_cruft_nr++] = p; - } - - QSORT(existing_cruft, existing_cruft_nr, existing_cruft_pack_cmp); - - for (i = 0; i < existing_cruft_nr; i++) { - size_t proposed; - - p = existing_cruft[i]; - proposed = st_add(total_size, p->pack_size); - - if (proposed <= max_size) { - total_size = proposed; + if (p->pack_size < combine_cruft_below_size) { fprintf(in, "-%s\n", pack_basename(p)); } else { retain_cruft_pack(existing, p); @@ -1086,13 +1053,13 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size, existing->non_kept_packs.items[i].string); strbuf_release(&buf); - free(existing_cruft); } static int write_cruft_pack(const struct pack_objects_args *args, const char *destination, const char *pack_prefix, const char *cruft_expiration, + unsigned long combine_cruft_below_size, struct string_list *names, struct existing_packs *existing) { @@ -1135,8 +1102,9 @@ static int write_cruft_pack(const struct pack_objects_args *args, in = xfdopen(cmd.in, "w"); for_each_string_list_item(item, names) fprintf(in, "%s-%s.pack\n", pack_prefix, item->string); - if (args->max_pack_size && !cruft_expiration) { - collapse_small_cruft_packs(in, args->max_pack_size, existing); + if (combine_cruft_below_size && !cruft_expiration) { + combine_small_cruft_packs(in, combine_cruft_below_size, + existing); } else { for_each_string_list_item(item, &existing->non_kept_packs) fprintf(in, "-%s.pack\n", item->string); @@ -1190,6 +1158,7 @@ int cmd_repack(int argc, const char *opt_window_memory = NULL; const char *opt_depth = NULL; const char *opt_threads = NULL; + unsigned long combine_cruft_below_size = 0ul; struct option builtin_repack_options[] = { OPT_BIT('a', NULL, &pack_everything, @@ -1202,6 +1171,9 @@ int cmd_repack(int argc, PACK_CRUFT), OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"), N_("with --cruft, expire objects older than this")), + OPT_MAGNITUDE(0, "combine-cruft-below-size", + &combine_cruft_below_size, + N_("with --cruft, only repack cruft packs smaller than this")), OPT_MAGNITUDE(0, "max-cruft-size", &cruft_po_args.max_pack_size, N_("with --cruft, limit the size of new cruft packs")), OPT_BOOL('d', NULL, &delete_redundant, @@ -1445,7 +1417,8 @@ int cmd_repack(int argc, cruft_po_args.quiet = po_args.quiet; ret = write_cruft_pack(&cruft_po_args, packtmp, pack_prefix, - cruft_expiration, &names, + cruft_expiration, + combine_cruft_below_size, &names, &existing); if (ret) goto cleanup; @@ -1472,10 +1445,17 @@ int cmd_repack(int argc, * generate an empty pack (since every object not in the * cruft pack generated above will have an mtime older * than the expiration). + * + * Pretend we don't have a `--combine-cruft-below-size` + * argument, since we're not selectively combining + * anything based on size to generate the limbo cruft + * pack, but rather removing all cruft packs from the + * main repository regardless of size. */ ret = write_cruft_pack(&cruft_po_args, expire_to, pack_prefix, NULL, + 0ul, &names, &existing); if (ret) diff --git a/builtin/replace.c b/builtin/replace.c index a4eaadff91..15ec0922ce 100644 --- a/builtin/replace.c +++ b/builtin/replace.c @@ -345,7 +345,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw) } strbuf_release(&ref); - tmpfile = git_pathdup("REPLACE_EDITOBJ"); + tmpfile = repo_git_path(the_repository, "REPLACE_EDITOBJ"); if (export_object(&old_oid, type, raw, tmpfile)) { free(tmpfile); return -1; diff --git a/builtin/rerere.c b/builtin/rerere.c index 41127e24e5..1312e79d89 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -4,9 +4,9 @@ #include "config.h" #include "gettext.h" #include "parse-options.h" - -#include "string-list.h" #include "rerere.h" +#include "strbuf.h" +#include "string-list.h" #include "xdiff/xdiff.h" #include "xdiff-interface.h" #include "pathspec.h" @@ -112,15 +112,18 @@ int cmd_rerere(int argc, merge_rr.items[i].util = NULL; } } else if (!strcmp(argv[0], "diff")) { + struct strbuf buf = STRBUF_INIT; if (setup_rerere(the_repository, &merge_rr, flags | RERERE_READONLY) < 0) return 0; for (size_t i = 0; i < merge_rr.nr; i++) { const char *path = merge_rr.items[i].string; const struct rerere_id *id = merge_rr.items[i].util; - if (diff_two(rerere_path(id, "preimage"), path, path, path)) - die(_("unable to generate diff for '%s'"), rerere_path(id, NULL)); + if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path)) + die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL)); } + + strbuf_release(&buf); } else usage_with_options(rerere_usage, options); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 428c866c05..490da33bec 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -789,8 +789,8 @@ int cmd_rev_parse(int argc, if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die(_("--git-path requires an argument")); - strbuf_reset(&buf); - print_path(git_path("%s", argv[i + 1]), prefix, + print_path(repo_git_path_replace(the_repository, &buf, + "%s", argv[i + 1]), prefix, format, DEFAULT_RELATIVE_IF_SHARED); i++; @@ -1083,7 +1083,7 @@ int cmd_rev_parse(int argc, die(_("Could not read the index")); if (the_repository->index->split_index) { const struct object_id *oid = &the_repository->index->split_index->base_oid; - const char *path = git_path("sharedindex.%s", oid_to_hex(oid)); + const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid)); print_path(path, prefix, format, DEFAULT_RELATIVE); } continue; diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 8d461008e2..c6e0e9d051 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "hex.h" @@ -151,7 +150,7 @@ static int send_pack_config(const char *k, const char *v, int cmd_send_pack(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { struct refspec rs = REFSPEC_INIT_PUSH; const char *remote_name = NULL; @@ -212,7 +211,7 @@ int cmd_send_pack(int argc, OPT_END() }; - git_config(send_pack_config, NULL); + repo_config(repo, send_pack_config, NULL); argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0); if (argc > 0) { dest = argv[0]; @@ -317,7 +316,7 @@ int cmd_send_pack(int argc, set_ref_status_for_push(remote_refs, args.send_mirror, args.force_update); - ret = send_pack(the_repository, &args, fd, conn, remote_refs, &extra_have); + ret = send_pack(repo, &args, fd, conn, remote_refs, &extra_have); if (helper_status) print_helper_status(remote_refs); diff --git a/builtin/stash.c b/builtin/stash.c index dbaa999cf1..cfbd92852a 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -13,7 +13,6 @@ #include "lockfile.h" #include "cache-tree.h" #include "unpack-trees.h" -#include "merge-recursive.h" #include "merge-ort-wrappers.h" #include "strvec.h" #include "run-command.h" diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f9b970f8a6..c1a8029714 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix, remote_key = xstrfmt("remote.%s.url", default_remote); free(default_remote); - submodule_to_gitdir(&sb, path); + submodule_to_gitdir(the_repository, &sb, path); strbuf_addstr(&sb, "/config"); if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) @@ -1826,7 +1826,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0); - p = git_pathdup_submodule(clone_data_path, "config"); + p = repo_submodule_path(the_repository, clone_data_path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), clone_data_path); diff --git a/builtin/tag.c b/builtin/tag.c index e8a344b926..d3e0943b73 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -667,7 +667,7 @@ int cmd_tag(int argc, if (create_tag_object) { if (force_sign_annotate && !annotate) opt.sign = 1; - path = git_pathdup("TAG_EDITMSG"); + path = repo_git_path(the_repository, "TAG_EDITMSG"); create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, &trailer_args, path); } diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 8383bcf404..c5a6dca856 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -668,6 +668,7 @@ int cmd_unpack_objects(int argc, the_hash_algo->init_fn(&ctx); unpack_all(); git_hash_update(&ctx, buffer, offset); + the_hash_algo->init_fn(&tmp_ctx); git_hash_clone(&tmp_ctx, &ctx); git_hash_final_oid(&oid, &tmp_ctx); if (strict) { diff --git a/builtin/update-ref.c b/builtin/update-ref.c index 4d35bdc4b4..1d541e13ad 100644 --- a/builtin/update-ref.c +++ b/builtin/update-ref.c @@ -179,7 +179,8 @@ static int parse_next_oid(const char **next, const char *end, (*next)++; *next = parse_arg(*next, &arg); if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else { /* Without -z, an empty value means all zeros: */ @@ -197,7 +198,8 @@ static int parse_next_oid(const char **next, const char *end, *next += arg.len; if (arg.len) { - if (repo_get_oid(the_repository, arg.buf, oid)) + if (repo_get_oid_with_flags(the_repository, arg.buf, oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) goto invalid; } else if (flags & PARSE_SHA1_ALLOW_EMPTY) { /* With -z, treat an empty value as all zeros: */ @@ -299,7 +301,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction, die("symref-update %s: expected old value", refname); if (!strcmp(old_arg, "oid")) { - if (repo_get_oid(the_repository, old_target, &old_oid)) + if (repo_get_oid_with_flags(the_repository, old_target, &old_oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("symref-update %s: invalid oid: %s", refname, old_target); have_old_oid = 1; @@ -772,7 +775,8 @@ int cmd_update_ref(int argc, refname = argv[0]; value = argv[1]; oldval = argv[2]; - if (repo_get_oid(the_repository, value, &oid)) + if (repo_get_oid_with_flags(the_repository, value, &oid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid SHA1", value); } @@ -783,7 +787,8 @@ int cmd_update_ref(int argc, * must not already exist: */ oidclr(&oldoid, the_repository->hash_algo); - else if (repo_get_oid(the_repository, oldval, &oldoid)) + else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid, + GET_OID_SKIP_AMBIGUITY_CHECK)) die("%s: not a valid old SHA1", oldval); } diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c index 779b7988ca..5f749a30da 100644 --- a/builtin/verify-commit.c +++ b/builtin/verify-commit.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -33,15 +32,15 @@ static int run_gpg_verify(struct commit *commit, unsigned flags) return ret; } -static int verify_commit(const char *name, unsigned flags) +static int verify_commit(struct repository *repo, const char *name, unsigned flags) { struct object_id oid; struct object *obj; - if (repo_get_oid(the_repository, name, &oid)) + if (repo_get_oid(repo, name, &oid)) return error("commit '%s' not found.", name); - obj = parse_object(the_repository, &oid); + obj = parse_object(repo, &oid); if (!obj) return error("%s: unable to read file.", name); if (obj->type != OBJ_COMMIT) @@ -54,7 +53,7 @@ static int verify_commit(const char *name, unsigned flags) int cmd_verify_commit(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -64,7 +63,7 @@ int cmd_verify_commit(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_commit_options, verify_commit_usage, PARSE_OPT_KEEP_ARGV0); @@ -78,7 +77,7 @@ int cmd_verify_commit(int argc, * was received in the process of writing the gpg input: */ signal(SIGPIPE, SIG_IGN); while (i < argc) - if (verify_commit(argv[i++], flags)) + if (verify_commit(repo, argv[i++], flags)) had_error = 1; return had_error; } diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c index f6b97048a5..ed1c40338f 100644 --- a/builtin/verify-tag.c +++ b/builtin/verify-tag.c @@ -5,7 +5,6 @@ * * Based on git-verify-tag.sh */ -#define USE_THE_REPOSITORY_VARIABLE #include "builtin.h" #include "config.h" #include "gettext.h" @@ -23,7 +22,7 @@ static const char * const verify_tag_usage[] = { int cmd_verify_tag(int argc, const char **argv, const char *prefix, - struct repository *repo UNUSED) + struct repository *repo) { int i = 1, verbose = 0, had_error = 0; unsigned flags = 0; @@ -35,7 +34,7 @@ int cmd_verify_tag(int argc, OPT_END() }; - git_config(git_default_config, NULL); + repo_config(repo, git_default_config, NULL); argc = parse_options(argc, argv, prefix, verify_tag_options, verify_tag_usage, PARSE_OPT_KEEP_ARGV0); @@ -56,7 +55,7 @@ int cmd_verify_tag(int argc, struct object_id oid; const char *name = argv[i++]; - if (repo_get_oid(the_repository, name, &oid)) { + if (repo_get_oid(repo, name, &oid)) { had_error = !!error("tag '%s' not found.", name); continue; } diff --git a/builtin/worktree.c b/builtin/worktree.c index c043d4d523..48448a8355 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -151,7 +151,7 @@ static int delete_git_dir(const char *id) struct strbuf sb = STRBUF_INIT; int ret; - strbuf_addstr(&sb, git_common_path("worktrees/%s", id)); + repo_common_path_append(the_repository, &sb, "worktrees/%s", id); ret = remove_dir_recursively(&sb, 0); if (ret < 0 && errno == ENOTDIR) ret = unlink(sb.buf); @@ -163,7 +163,9 @@ static int delete_git_dir(const char *id) static void delete_worktrees_dir_if_empty(void) { - rmdir(git_path("worktrees")); /* ignore failed removal */ + char *path = repo_git_path(the_repository, "worktrees"); + rmdir(path); /* ignore failed removal */ + free(path); } static void prune_worktree(const char *id, const char *reason) @@ -212,8 +214,13 @@ static void prune_worktrees(void) struct strbuf reason = STRBUF_INIT; struct strbuf main_path = STRBUF_INIT; struct string_list kept = STRING_LIST_INIT_DUP; - DIR *dir = opendir(git_path("worktrees")); + char *path; + DIR *dir; struct dirent *d; + + path = repo_git_path(the_repository, "worktrees"); + dir = opendir(path); + free(path); if (!dir) return; while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { @@ -337,7 +344,7 @@ static void check_candidate_path(const char *path, static void copy_sparse_checkout(const char *worktree_git_dir) { - char *from_file = git_pathdup("info/sparse-checkout"); + char *from_file = repo_git_path(the_repository, "info/sparse-checkout"); char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir); if (file_exists(from_file)) { @@ -353,7 +360,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir) static void copy_filtered_worktree_config(const char *worktree_git_dir) { - char *from_file = git_pathdup("config.worktree"); + char *from_file = repo_git_path(the_repository, "config.worktree"); char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir); if (file_exists(from_file)) { @@ -457,7 +464,7 @@ static int add_worktree(const char *path, const char *refname, BUG("How come '%s' becomes empty after sanitization?", sb.buf); strbuf_reset(&sb); name = sb_name.buf; - git_path_buf(&sb_repo, "worktrees/%s", name); + repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name); len = sb_repo.len; if (safe_create_leading_directories_const(sb_repo.buf)) die_errno(_("could not create leading directories of '%s'"), @@ -657,8 +664,9 @@ static int can_use_local_refs(const struct add_opts *opts) if (!opts->quiet) { struct strbuf path = STRBUF_INIT; struct strbuf contents = STRBUF_INIT; + char *wt_gitdir = get_worktree_git_dir(NULL); - strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); + strbuf_add_real_path(&path, wt_gitdir); strbuf_addstr(&path, "/HEAD"); strbuf_read_file(&contents, path.buf, 64); strbuf_stripspace(&contents, NULL); @@ -670,6 +678,7 @@ static int can_use_local_refs(const struct add_opts *opts) path.buf, contents.buf); strbuf_release(&path); strbuf_release(&contents); + free(wt_gitdir); } return 1; } @@ -1100,6 +1109,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0); if (ac != 1) @@ -1120,9 +1130,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix, die(_("'%s' is already locked"), av[0]); } - write_file(git_common_path("worktrees/%s/locked", wt->id), - "%s", reason); + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + write_file(path, "%s", reason); + free_worktrees(worktrees); + free(path); return 0; } @@ -1133,6 +1145,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; int ret; ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0); @@ -1147,8 +1160,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, die(_("The main working tree cannot be locked or unlocked")); if (!worktree_lock_reason(wt)) die(_("'%s' is not locked"), av[0]); - ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id)); + + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + ret = unlink_or_warn(path); + free_worktrees(worktrees); + free(path); return ret; } @@ -1157,6 +1174,9 @@ static void validate_no_submodules(const struct worktree *wt) struct index_state istate = INDEX_STATE_INIT(the_repository); struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; + char *wt_gitdir; + + wt_gitdir = get_worktree_git_dir(wt); if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* @@ -1166,7 +1186,7 @@ static void validate_no_submodules(const struct worktree *wt) */ found_submodules = 1; } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) { + wt_gitdir) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; int err; @@ -1185,6 +1205,7 @@ static void validate_no_submodules(const struct worktree *wt) } discard_index(&istate); strbuf_release(&path); + free(wt_gitdir); if (found_submodules) die(_("working trees containing submodules cannot be moved or removed")); |
