aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c16
-rw-r--r--builtin/backfill.c147
-rw-r--r--builtin/blame.c6
-rw-r--r--builtin/branch.c7
-rw-r--r--builtin/bugreport.c15
-rw-r--r--builtin/check-mailmap.c2
-rw-r--r--builtin/check-ref-format.c4
-rw-r--r--builtin/checkout--worker.c6
-rw-r--r--builtin/checkout-index.c49
-rw-r--r--builtin/clone.c356
-rw-r--r--builtin/commit-graph.c1
-rw-r--r--builtin/commit-tree.c4
-rw-r--r--builtin/commit.c18
-rw-r--r--builtin/config.c8
-rw-r--r--builtin/credential-cache--daemon.c4
-rw-r--r--builtin/credential.c9
-rw-r--r--builtin/diagnose.c4
-rw-r--r--builtin/diff-files.c3
-rw-r--r--builtin/diff-index.c3
-rw-r--r--builtin/diff-pairs.c207
-rw-r--r--builtin/diff-tree.c3
-rw-r--r--builtin/difftool.c95
-rw-r--r--builtin/fast-export.c188
-rw-r--r--builtin/fast-import.c59
-rw-r--r--builtin/fetch-pack.c2
-rw-r--r--builtin/fetch.c69
-rw-r--r--builtin/for-each-ref.c6
-rw-r--r--builtin/fsck.c55
-rw-r--r--builtin/fsmonitor--daemon.c4
-rw-r--r--builtin/gc.c40
-rw-r--r--builtin/get-tar-commit-id.c4
-rw-r--r--builtin/grep.c4
-rw-r--r--builtin/help.c4
-rw-r--r--builtin/index-pack.c70
-rw-r--r--builtin/init-db.c8
-rw-r--r--builtin/log.c63
-rw-r--r--builtin/ls-files.c36
-rw-r--r--builtin/mailinfo.c2
-rw-r--r--builtin/mailsplit.c4
-rw-r--r--builtin/merge-base.c4
-rw-r--r--builtin/merge-index.c7
-rw-r--r--builtin/merge-ours.c3
-rw-r--r--builtin/merge-recursive.c6
-rw-r--r--builtin/merge-tree.c11
-rw-r--r--builtin/merge.c4
-rw-r--r--builtin/notes.c9
-rw-r--r--builtin/pack-objects.c214
-rw-r--r--builtin/pack-redundant.c3
-rw-r--r--builtin/pack-refs.c8
-rw-r--r--builtin/patch-id.c14
-rw-r--r--builtin/prune.c3
-rw-r--r--builtin/push.c2
-rw-r--r--builtin/rebase.c8
-rw-r--r--builtin/receive-pack.c30
-rw-r--r--builtin/refs.c7
-rw-r--r--builtin/remote-ext.c2
-rw-r--r--builtin/remote-fd.c1
-rw-r--r--builtin/remote.c13
-rw-r--r--builtin/repack.c16
-rw-r--r--builtin/replace.c2
-rw-r--r--builtin/replay.c7
-rw-r--r--builtin/rerere.c11
-rw-r--r--builtin/rev-list.c112
-rw-r--r--builtin/rev-parse.c8
-rw-r--r--builtin/send-pack.c7
-rw-r--r--builtin/show-index.c2
-rw-r--r--builtin/submodule--helper.c4
-rw-r--r--builtin/tag.c3
-rw-r--r--builtin/unpack-file.c8
-rw-r--r--builtin/unpack-objects.c49
-rw-r--r--builtin/update-index.c4
-rw-r--r--builtin/update-ref.c15
-rw-r--r--builtin/update-server-info.c8
-rw-r--r--builtin/upload-archive.c6
-rw-r--r--builtin/upload-pack.c6
-rw-r--r--builtin/var.c3
-rw-r--r--builtin/verify-commit.c13
-rw-r--r--builtin/verify-tag.c8
-rw-r--r--builtin/worktree.c43
79 files changed, 1559 insertions, 710 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 1338b606fe..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;
@@ -1211,7 +1211,7 @@ static int parse_mail(struct am_state *state, const char *mail)
int ret = 0;
struct mailinfo mi;
- setup_mailinfo(&mi);
+ setup_mailinfo(the_repository, &mi);
if (state->utf8)
mi.metainfo_charset = get_commit_output_encoding();
@@ -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."));
@@ -1786,7 +1787,7 @@ static int do_interactive(struct am_state *state)
}
strbuf_release(&msg);
} else if (*reply == 'v' || *reply == 'V') {
- const char *pager = git_pager(1);
+ const char *pager = git_pager(the_repository, 1);
struct child_process cp = CHILD_PROCESS_INIT;
if (!pager)
@@ -2246,7 +2247,7 @@ static int show_patch(struct am_state *state, enum resume_type resume_mode)
if (len < 0)
die_errno(_("failed to read '%s'"), patch_path);
- setup_pager();
+ setup_pager(the_repository);
write_in_full(1, sb.buf, sb.len);
strbuf_release(&sb);
return 0;
@@ -2427,8 +2428,7 @@ int cmd_am(int argc,
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(usage, options);
+ show_usage_with_options_if_asked(argc, argv, usage, options);
git_config(git_default_config, NULL);
diff --git a/builtin/backfill.c b/builtin/backfill.c
new file mode 100644
index 0000000000..33e1ea2f84
--- /dev/null
+++ b/builtin/backfill.c
@@ -0,0 +1,147 @@
+/* We need this macro to access core_apply_sparse_checkout */
+#define USE_THE_REPOSITORY_VARIABLE
+
+#include "builtin.h"
+#include "git-compat-util.h"
+#include "config.h"
+#include "parse-options.h"
+#include "repository.h"
+#include "commit.h"
+#include "dir.h"
+#include "environment.h"
+#include "hex.h"
+#include "tree.h"
+#include "tree-walk.h"
+#include "object.h"
+#include "object-store-ll.h"
+#include "oid-array.h"
+#include "oidset.h"
+#include "promisor-remote.h"
+#include "strmap.h"
+#include "string-list.h"
+#include "revision.h"
+#include "trace2.h"
+#include "progress.h"
+#include "packfile.h"
+#include "path-walk.h"
+
+static const char * const builtin_backfill_usage[] = {
+ N_("git backfill [--min-batch-size=<n>] [--[no-]sparse]"),
+ NULL
+};
+
+struct backfill_context {
+ struct repository *repo;
+ struct oid_array current_batch;
+ size_t min_batch_size;
+ int sparse;
+};
+
+static void backfill_context_clear(struct backfill_context *ctx)
+{
+ oid_array_clear(&ctx->current_batch);
+}
+
+static void download_batch(struct backfill_context *ctx)
+{
+ promisor_remote_get_direct(ctx->repo,
+ ctx->current_batch.oid,
+ ctx->current_batch.nr);
+ oid_array_clear(&ctx->current_batch);
+
+ /*
+ * We likely have a new packfile. Add it to the packed list to
+ * avoid possible duplicate downloads of the same objects.
+ */
+ reprepare_packed_git(ctx->repo);
+}
+
+static int fill_missing_blobs(const char *path UNUSED,
+ struct oid_array *list,
+ enum object_type type,
+ void *data)
+{
+ struct backfill_context *ctx = data;
+
+ if (type != OBJ_BLOB)
+ return 0;
+
+ for (size_t i = 0; i < list->nr; i++) {
+ if (!has_object(ctx->repo, &list->oid[i],
+ OBJECT_INFO_FOR_PREFETCH))
+ oid_array_append(&ctx->current_batch, &list->oid[i]);
+ }
+
+ if (ctx->current_batch.nr >= ctx->min_batch_size)
+ download_batch(ctx);
+
+ return 0;
+}
+
+static int do_backfill(struct backfill_context *ctx)
+{
+ struct rev_info revs;
+ struct path_walk_info info = PATH_WALK_INFO_INIT;
+ int ret;
+
+ if (ctx->sparse) {
+ CALLOC_ARRAY(info.pl, 1);
+ if (get_sparse_checkout_patterns(info.pl)) {
+ path_walk_info_clear(&info);
+ return error(_("problem loading sparse-checkout"));
+ }
+ }
+
+ repo_init_revisions(ctx->repo, &revs, "");
+ handle_revision_arg("HEAD", &revs, 0, 0);
+
+ info.blobs = 1;
+ info.tags = info.commits = info.trees = 0;
+
+ info.revs = &revs;
+ info.path_fn = fill_missing_blobs;
+ info.path_fn_data = ctx;
+
+ ret = walk_objects_by_path(&info);
+
+ /* Download the objects that did not fill a batch. */
+ if (!ret)
+ download_batch(ctx);
+
+ path_walk_info_clear(&info);
+ release_revisions(&revs);
+ return ret;
+}
+
+int cmd_backfill(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+ int result;
+ struct backfill_context ctx = {
+ .repo = repo,
+ .current_batch = OID_ARRAY_INIT,
+ .min_batch_size = 50000,
+ .sparse = 0,
+ };
+ struct option options[] = {
+ OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size,
+ N_("Minimum number of objects to request at a time")),
+ OPT_BOOL(0, "sparse", &ctx.sparse,
+ N_("Restrict the missing objects to the current sparse-checkout")),
+ OPT_END(),
+ };
+
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_backfill_usage, options);
+
+ argc = parse_options(argc, argv, prefix, options, builtin_backfill_usage,
+ 0);
+
+ repo_config(repo, git_default_config, NULL);
+
+ if (ctx.sparse < 0)
+ ctx.sparse = core_apply_sparse_checkout;
+
+ result = do_backfill(&ctx);
+ backfill_context_clear(&ctx);
+ return result;
+}
diff --git a/builtin/blame.c b/builtin/blame.c
index 7555c445ab..c470654c7e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1194,14 +1194,16 @@ parse_done:
sb.found_guilty_entry = &found_guilty_entry;
sb.found_guilty_entry_data = &pi;
if (show_progress)
- pi.progress = start_delayed_progress(_("Blaming lines"), num_lines);
+ pi.progress = start_delayed_progress(the_repository,
+ _("Blaming lines"),
+ num_lines);
assign_blame(&sb, opt);
stop_progress(&pi.progress);
if (!incremental)
- setup_pager();
+ setup_pager(the_repository);
else
goto cleanup;
diff --git a/builtin/branch.c b/builtin/branch.c
index 6e7b0cfddb..c150131bd9 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -473,7 +473,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
if (verify_ref_format(format))
die(_("unable to parse format string"));
- filter_ahead_behind(the_repository, format, &array);
+ filter_ahead_behind(the_repository, &array);
ref_array_sort(sorting, &array);
if (column_active(colopts)) {
@@ -784,8 +784,8 @@ int cmd_branch(int argc,
filter.kind = FILTER_REFS_BRANCHES;
filter.abbrev = -1;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_branch_usage, options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_branch_usage, options);
/*
* Try to set sort keys from config. If config does not set any,
@@ -884,7 +884,6 @@ int cmd_branch(int argc,
string_list_clear(&output, 0);
ref_sorting_release(sorting);
ref_filter_clear(&filter);
- ref_format_clear(&format);
ret = 0;
goto out;
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 7c2df035c9..66d64bfd5a 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -12,10 +12,10 @@
#include "diagnose.h"
#include "object-file.h"
#include "setup.h"
+#include "version.h"
static void get_system_info(struct strbuf *sys_info)
{
- struct utsname uname_info;
char *shell = NULL;
/* get git version from native cmd */
@@ -24,16 +24,7 @@ static void get_system_info(struct strbuf *sys_info)
/* system call for other version info */
strbuf_addstr(sys_info, "uname: ");
- if (uname(&uname_info))
- strbuf_addf(sys_info, _("uname() failed with error '%s' (%d)\n"),
- strerror(errno),
- errno);
- else
- strbuf_addf(sys_info, "%s %s %s %s\n",
- uname_info.sysname,
- uname_info.release,
- uname_info.version,
- uname_info.machine);
+ get_uname_info(sys_info, 1);
strbuf_addstr(sys_info, _("compiler info: "));
get_compiler_info(sys_info);
@@ -167,7 +158,7 @@ int cmd_bugreport(int argc,
strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0);
strbuf_addstr(&zip_path, ".zip");
- if (create_diagnostics_archive(&zip_path, diagnose))
+ if (create_diagnostics_archive(the_repository, &zip_path, diagnose))
die_errno(_("unable to create diagnostics archive %s"), zip_path.buf);
strbuf_release(&zip_path);
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index df00b5ee13..be2cebe121 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -35,7 +35,7 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
mail = ident.mail_begin;
maillen = ident.mail_end - ident.mail_begin;
} else {
- name = NULL;
+ name = "";
namelen = 0;
mail = contact;
maillen = strlen(contact);
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index cef1ffe3ce..5d80afeec0 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -64,8 +64,8 @@ int cmd_check_ref_format(int argc,
BUG_ON_NON_EMPTY_PREFIX(prefix);
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(builtin_check_ref_format_usage);
+ show_usage_if_asked(argc, argv,
+ builtin_check_ref_format_usage);
if (argc == 3 && !strcmp(argv[1], "--branch"))
return check_ref_format_branch(argv[2]);
diff --git a/builtin/checkout--worker.c b/builtin/checkout--worker.c
index b81002a1df..da9345a44b 100644
--- a/builtin/checkout--worker.c
+++ b/builtin/checkout--worker.c
@@ -128,9 +128,9 @@ int cmd_checkout__worker(int argc,
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(checkout_worker_usage,
- checkout_worker_options);
+ show_usage_with_options_if_asked(argc, argv,
+ checkout_worker_usage,
+ checkout_worker_options);
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, checkout_worker_options,
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index a81501098d..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;
@@ -250,22 +249,22 @@ int cmd_checkout_index(int argc,
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_checkout_index_usage,
- builtin_checkout_index_options);
- git_config(git_default_config, NULL);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_checkout_index_usage,
+ builtin_checkout_index_options);
+ 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 fd001d800c..88276e5b7a 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -56,42 +56,30 @@
* - dropping use-separate-remote and no-separate-remote compatibility
*
*/
-static const char * const builtin_clone_usage[] = {
- N_("git clone [<options>] [--] <repo> [<dir>]"),
- NULL
+
+struct clone_opts {
+ int wants_head;
+ int detach;
};
+#define CLONE_OPTS_INIT { \
+ .wants_head = 1 /* default enabled */ \
+}
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
static int option_local = -1, option_no_hardlinks, option_shared;
-static int option_no_tags;
+static int option_tags = 1; /* default enabled */
static int option_shallow_submodules;
-static int option_reject_shallow = -1; /* unspecified */
static int config_reject_shallow = -1; /* unspecified */
-static int deepen;
-static char *option_template, *option_depth, *option_since;
-static char *option_origin = NULL;
static char *remote_name = NULL;
static char *option_branch = NULL;
-static struct string_list option_not = STRING_LIST_INIT_NODUP;
-static const char *real_git_dir;
-static const char *ref_format;
-static const char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
-static int option_progress = -1;
-static int option_sparse_checkout;
-static enum transport_family family;
-static struct string_list option_config = STRING_LIST_INIT_NODUP;
static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
-static int option_dissociate;
static int max_jobs = -1;
static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
-static int option_filter_submodules = -1; /* unspecified */
static int config_filter_submodules = -1; /* unspecified */
-static struct string_list server_options = STRING_LIST_INIT_NODUP;
static int option_remote_submodules;
-static const char *bundle_uri;
static int recurse_submodules_cb(const struct option *opt,
const char *arg, int unset)
@@ -107,78 +95,6 @@ static int recurse_submodules_cb(const struct option *opt,
return 0;
}
-static struct option builtin_clone_options[] = {
- OPT__VERBOSITY(&option_verbosity),
- OPT_BOOL(0, "progress", &option_progress,
- N_("force progress reporting")),
- OPT_BOOL(0, "reject-shallow", &option_reject_shallow,
- N_("don't clone shallow repository")),
- OPT_BOOL('n', "no-checkout", &option_no_checkout,
- N_("don't create a checkout")),
- OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
- OPT_HIDDEN_BOOL(0, "naked", &option_bare,
- N_("create a bare repository")),
- OPT_BOOL(0, "mirror", &option_mirror,
- N_("create a mirror repository (implies --bare)")),
- OPT_BOOL('l', "local", &option_local,
- N_("to clone from a local repository")),
- OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
- N_("don't use local hardlinks, always copy")),
- OPT_BOOL('s', "shared", &option_shared,
- N_("setup as shared repository")),
- { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
- N_("pathspec"), N_("initialize submodules in the clone"),
- PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
- OPT_ALIAS(0, "recursive", "recurse-submodules"),
- OPT_INTEGER('j', "jobs", &max_jobs,
- N_("number of submodules cloned in parallel")),
- OPT_STRING(0, "template", &option_template, N_("template-directory"),
- N_("directory from which templates will be used")),
- OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
- N_("reference repository")),
- OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
- N_("repo"), N_("reference repository")),
- OPT_BOOL(0, "dissociate", &option_dissociate,
- N_("use --reference only while cloning")),
- OPT_STRING('o', "origin", &option_origin, N_("name"),
- N_("use <name> instead of 'origin' to track upstream")),
- OPT_STRING('b', "branch", &option_branch, N_("branch"),
- N_("checkout <branch> instead of the remote's HEAD")),
- OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
- N_("path to git-upload-pack on the remote")),
- OPT_STRING(0, "depth", &option_depth, N_("depth"),
- N_("create a shallow clone of that depth")),
- OPT_STRING(0, "shallow-since", &option_since, N_("time"),
- N_("create a shallow clone since a specific time")),
- OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"),
- N_("deepen history of shallow clone, excluding ref")),
- OPT_BOOL(0, "single-branch", &option_single_branch,
- N_("clone only one branch, HEAD or --branch")),
- OPT_BOOL(0, "no-tags", &option_no_tags,
- N_("don't clone any tags, and make later fetches not to follow them")),
- OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
- N_("any cloned submodules will be shallow")),
- OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
- N_("separate git dir from working tree")),
- OPT_STRING(0, "ref-format", &ref_format, N_("format"),
- N_("specify the reference format to use")),
- OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
- N_("set config inside the new repository")),
- OPT_STRING_LIST(0, "server-option", &server_options,
- N_("server-specific"), N_("option to transmit")),
- OPT_IPVERSION(&family),
- OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
- OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules,
- N_("apply partial clone filters to submodules")),
- OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
- N_("any cloned submodules will use their remote-tracking branch")),
- OPT_BOOL(0, "sparse", &option_sparse_checkout,
- N_("initialize sparse-checkout file to include only files at root")),
- OPT_STRING(0, "bundle-uri", &bundle_uri,
- N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")),
- OPT_END()
-};
-
static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
{
static const char *suffix[] = { "/.git", "", ".git/.git", ".git" };
@@ -426,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)
@@ -521,51 +439,31 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
return ref;
}
-static struct ref *wanted_peer_refs(const struct ref *refs,
- struct refspec *refspec)
+static struct ref *wanted_peer_refs(struct clone_opts *opts,
+ const struct ref *refs,
+ struct refspec *refspec)
{
- struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
- struct ref *local_refs = head;
- struct ref **tail = head ? &head->next : &local_refs;
- struct refspec_item tag_refspec;
-
- refspec_item_init(&tag_refspec, TAG_REFSPEC, 0);
-
- if (option_single_branch) {
- struct ref *remote_head = NULL;
-
- if (!option_branch)
- remote_head = guess_remote_head(head, refs, 0);
- else {
- free_one_ref(head);
- local_refs = head = NULL;
- tail = &local_refs;
- remote_head = copy_ref(find_remote_branch(refs, option_branch));
- }
-
- if (!remote_head && option_branch)
- warning(_("Could not find remote branch %s to clone."),
- option_branch);
- else {
- int i;
- for (i = 0; i < refspec->nr; i++)
- get_fetch_map(remote_head, &refspec->items[i],
- &tail, 0);
-
- /* if --branch=tag, pull the requested tag explicitly */
- get_fetch_map(remote_head, &tag_refspec, &tail, 0);
- }
- free_refs(remote_head);
- } else {
- int i;
- for (i = 0; i < refspec->nr; i++)
- get_fetch_map(refs, &refspec->items[i], &tail, 0);
+ struct ref *local_refs = NULL;
+ struct ref **tail = &local_refs;
+ struct ref *to_free = NULL;
+
+ if (opts->wants_head) {
+ struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
+ if (head)
+ tail_link_ref(head, &tail);
+ if (option_single_branch)
+ refs = to_free = guess_remote_head(head, refs, 0);
+ } else if (option_single_branch) {
+ local_refs = NULL;
+ tail = &local_refs;
+ refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
}
- if (!option_mirror && !option_single_branch && !option_no_tags)
- get_fetch_map(refs, &tag_refspec, &tail, 0);
+ for (size_t i = 0; i < refspec->nr; i++)
+ get_fetch_map(refs, &refspec->items[i], &tail, 0);
+
+ free_one_ref(to_free);
- refspec_item_clear(&tag_refspec);
return local_refs;
}
@@ -654,7 +552,7 @@ static void update_remote_refs(const struct ref *refs,
if (refs) {
write_remote_refs(mapped_refs);
- if (option_single_branch && !option_no_tags)
+ if (option_single_branch && option_tags)
write_followtags(refs, msg);
}
@@ -670,11 +568,11 @@ static void update_remote_refs(const struct ref *refs,
}
}
-static void update_head(const struct ref *our, const struct ref *remote,
+static void update_head(struct clone_opts *opts, const struct ref *our, const struct ref *remote,
const char *unborn, const char *msg)
{
const char *head;
- if (our && skip_prefix(our->name, "refs/heads/", &head)) {
+ if (our && !opts->detach && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0)
die(_("unable to update HEAD"));
@@ -685,8 +583,9 @@ static void update_head(const struct ref *our, const struct ref *remote,
install_branch_config(0, head, remote_name, our->name);
}
} else if (our) {
- struct commit *c = lookup_commit_reference(the_repository,
- &our->old_oid);
+ struct commit *c = lookup_commit_or_die(&our->old_oid,
+ our->name);
+
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
refs_update_ref(get_main_ref_store(the_repository), msg,
"HEAD", &c->object.oid, NULL, REF_NO_DEREF,
@@ -938,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;
@@ -989,10 +888,108 @@ int cmd_clone(int argc,
int hash_algo;
enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
const int do_not_override_repo_unix_permissions = -1;
+ int option_reject_shallow = -1; /* unspecified */
+ int deepen = 0;
+ char *option_template = NULL, *option_depth = NULL, *option_since = NULL;
+ char *option_origin = NULL;
+ struct string_list option_not = STRING_LIST_INIT_NODUP;
+ const char *real_git_dir = NULL;
+ const char *ref_format = NULL;
+ const char *option_upload_pack = "git-upload-pack";
+ int option_progress = -1;
+ int option_sparse_checkout = 0;
+ enum transport_family family = TRANSPORT_FAMILY_ALL;
+ struct string_list option_config = STRING_LIST_INIT_DUP;
+ int option_dissociate = 0;
+ int option_filter_submodules = -1; /* unspecified */
+ struct string_list server_options = STRING_LIST_INIT_NODUP;
+ const char *bundle_uri = NULL;
+ char *option_rev = NULL;
+
+ struct clone_opts opts = CLONE_OPTS_INIT;
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
+ struct option builtin_clone_options[] = {
+ OPT__VERBOSITY(&option_verbosity),
+ OPT_BOOL(0, "progress", &option_progress,
+ N_("force progress reporting")),
+ OPT_BOOL(0, "reject-shallow", &option_reject_shallow,
+ N_("don't clone shallow repository")),
+ OPT_BOOL('n', "no-checkout", &option_no_checkout,
+ N_("don't create a checkout")),
+ OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
+ OPT_HIDDEN_BOOL(0, "naked", &option_bare,
+ N_("create a bare repository")),
+ OPT_BOOL(0, "mirror", &option_mirror,
+ N_("create a mirror repository (implies --bare)")),
+ OPT_BOOL('l', "local", &option_local,
+ N_("to clone from a local repository")),
+ OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
+ N_("don't use local hardlinks, always copy")),
+ OPT_BOOL('s', "shared", &option_shared,
+ N_("setup as shared repository")),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
+ N_("pathspec"), N_("initialize submodules in the clone"),
+ PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
+ OPT_ALIAS(0, "recursive", "recurse-submodules"),
+ OPT_INTEGER('j', "jobs", &max_jobs,
+ N_("number of submodules cloned in parallel")),
+ OPT_STRING(0, "template", &option_template, N_("template-directory"),
+ N_("directory from which templates will be used")),
+ OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
+ N_("reference repository")),
+ OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
+ N_("repo"), N_("reference repository")),
+ OPT_BOOL(0, "dissociate", &option_dissociate,
+ N_("use --reference only while cloning")),
+ OPT_STRING('o', "origin", &option_origin, N_("name"),
+ N_("use <name> instead of 'origin' to track upstream")),
+ OPT_STRING('b', "branch", &option_branch, N_("branch"),
+ N_("checkout <branch> instead of the remote's HEAD")),
+ OPT_STRING(0, "revision", &option_rev, N_("rev"),
+ N_("clone single revision <rev> and check out")),
+ OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
+ N_("path to git-upload-pack on the remote")),
+ OPT_STRING(0, "depth", &option_depth, N_("depth"),
+ N_("create a shallow clone of that depth")),
+ OPT_STRING(0, "shallow-since", &option_since, N_("time"),
+ N_("create a shallow clone since a specific time")),
+ OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"),
+ N_("deepen history of shallow clone, excluding ref")),
+ OPT_BOOL(0, "single-branch", &option_single_branch,
+ N_("clone only one branch, HEAD or --branch")),
+ OPT_BOOL(0, "tags", &option_tags,
+ N_("clone tags, and make later fetches not to follow them")),
+ OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
+ N_("any cloned submodules will be shallow")),
+ OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+ N_("separate git dir from working tree")),
+ OPT_STRING(0, "ref-format", &ref_format, N_("format"),
+ N_("specify the reference format to use")),
+ OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
+ N_("set config inside the new repository")),
+ OPT_STRING_LIST(0, "server-option", &server_options,
+ N_("server-specific"), N_("option to transmit")),
+ OPT_IPVERSION(&family),
+ OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
+ OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules,
+ N_("apply partial clone filters to submodules")),
+ OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
+ N_("any cloned submodules will use their remote-tracking branch")),
+ OPT_BOOL(0, "sparse", &option_sparse_checkout,
+ N_("initialize sparse-checkout file to include only files at root")),
+ OPT_STRING(0, "bundle-uri", &bundle_uri,
+ N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")),
+ OPT_END()
+ };
+
+ const char * const builtin_clone_usage[] = {
+ N_("git clone [<options>] [--] <repo> [<dir>]"),
+ NULL
+ };
+
packet_trace_identity("clone");
git_config(git_clone_config, NULL);
@@ -1019,8 +1016,10 @@ int cmd_clone(int argc,
die(_("unknown ref storage format '%s'"), ref_format);
}
- if (option_mirror)
+ if (option_mirror) {
option_bare = 1;
+ option_tags = 0;
+ }
if (option_bare) {
if (real_git_dir)
@@ -1138,8 +1137,8 @@ int cmd_clone(int argc,
for_each_string_list_item(item, &option_recurse_submodules) {
strbuf_addf(&sb, "submodule.active=%s",
item->string);
- string_list_append(&option_config,
- strbuf_detach(&sb, NULL));
+ string_list_append(&option_config, sb.buf);
+ strbuf_reset(&sb);
}
if (!git_config_get_bool("submodule.stickyRecursiveClone", &val) &&
@@ -1161,6 +1160,8 @@ int cmd_clone(int argc,
string_list_append(&option_config,
"submodule.alternateErrorStrategy=info");
}
+
+ strbuf_release(&sb);
}
/*
@@ -1220,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
@@ -1285,7 +1286,7 @@ int cmd_clone(int argc,
strbuf_addstr(&branch_top, src_ref_prefix);
git_config_set("core.bare", "true");
- } else {
+ } else if (!option_rev) {
strbuf_addf(&branch_top, "refs/remotes/%s/", remote_name);
}
@@ -1293,7 +1294,7 @@ int cmd_clone(int argc,
git_config_set(key.buf, repo);
strbuf_reset(&key);
- if (option_no_tags) {
+ if (!option_tags) {
strbuf_addf(&key, "remote.%s.tagOpt", remote_name);
git_config_set(key.buf, "--no-tags");
strbuf_reset(&key);
@@ -1304,8 +1305,9 @@ int cmd_clone(int argc,
remote = remote_get_early(remote_name);
- refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
- branch_top.buf);
+ if (!option_rev)
+ refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
+ branch_top.buf);
path = get_repo_path(remote->url.v[0], &is_bundle);
is_local = option_local != 0 && path && !is_bundle;
@@ -1348,6 +1350,11 @@ int cmd_clone(int argc,
transport_set_option(transport, TRANS_OPT_KEEP, "yes");
+ die_for_incompatible_opt2(!!option_rev, "--revision",
+ !!option_branch, "--branch");
+ die_for_incompatible_opt2(!!option_rev, "--revision",
+ option_mirror, "--mirror");
+
if (reject_shallow)
transport_set_option(transport, TRANS_OPT_REJECT_SHALLOW, "1");
if (option_depth)
@@ -1359,9 +1366,13 @@ int cmd_clone(int argc,
if (option_not.nr)
transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
(const char *)&option_not);
- if (option_single_branch)
+ if (option_single_branch) {
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
+ if (option_branch)
+ opts.wants_head = 0;
+ }
+
if (option_upload_pack)
transport_set_option(transport, TRANS_OPT_UPLOADPACK,
option_upload_pack);
@@ -1380,15 +1391,38 @@ int cmd_clone(int argc,
if (transport->smart_options && !deepen && !filter_options.choice)
transport->smart_options->check_self_contained_and_connected = 1;
- strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
+ if (option_rev) {
+ option_tags = 0;
+ option_single_branch = 0;
+ opts.wants_head = 0;
+ opts.detach = 1;
+
+ refspec_append(&remote->fetch, option_rev);
+ }
+
+ if (option_tags || option_branch)
+ /*
+ * Add tags refspec when user asked for tags (implicitly) or
+ * specified --branch, whose argument might be a tag.
+ */
+ refspec_append(&remote->fetch, TAG_REFSPEC);
+
refspec_ref_prefixes(&remote->fetch,
&transport_ls_refs_options.ref_prefixes);
if (option_branch)
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
option_branch);
- if (!option_no_tags)
- strvec_push(&transport_ls_refs_options.ref_prefixes,
- "refs/tags/");
+
+ /*
+ * As part of transport_get_remote_refs() the server tells us the hash
+ * algorithm, which we require to initialize the repo. But calling that
+ * function without any ref prefix, will cause the server to announce
+ * all known refs. If the argument passed to --revision was a hex oid,
+ * ref_prefixes will be empty so we fall back to asking about HEAD to
+ * reduce traffic from the server.
+ */
+ if (opts.wants_head || transport_ls_refs_options.ref_prefixes.nr == 0)
+ strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
@@ -1465,7 +1499,7 @@ int cmd_clone(int argc,
}
if (refs)
- mapped_refs = wanted_peer_refs(refs, &remote->fetch);
+ mapped_refs = wanted_peer_refs(&opts, refs, &remote->fetch);
if (mapped_refs) {
/*
@@ -1498,6 +1532,11 @@ int cmd_clone(int argc,
if (!our_head_points_at)
die(_("Remote branch %s not found in upstream %s"),
option_branch, remote_name);
+ } else if (option_rev) {
+ our_head_points_at = mapped_refs;
+ if (!our_head_points_at)
+ die(_("Remote revision %s not found in upstream %s"),
+ option_rev, remote_name);
} else if (remote_head_points_at) {
our_head_points_at = remote_head_points_at;
} else if (remote_head) {
@@ -1536,8 +1575,9 @@ int cmd_clone(int argc,
free(to_free);
}
- write_refspec_config(src_ref_prefix, our_head_points_at,
- remote_head_points_at, &branch_top);
+ if (!option_rev)
+ write_refspec_config(src_ref_prefix, our_head_points_at,
+ remote_head_points_at, &branch_top);
if (filter_options.choice)
partial_clone_register(remote_name, &filter_options);
@@ -1553,7 +1593,7 @@ int cmd_clone(int argc,
branch_top.buf, reflog_msg.buf, transport,
!is_local);
- update_head(our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
+ update_head(&opts, our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
/*
* We want to show progress for recursive submodule clones iff
@@ -1578,6 +1618,10 @@ int cmd_clone(int argc,
err = checkout(submodule_progress, filter_submodules,
ref_storage_format);
+ string_list_clear(&option_not, 0);
+ string_list_clear(&option_config, 0);
+ string_list_clear(&server_options, 0);
+
free(remote_name);
strbuf_release(&reflog_msg);
strbuf_release(&branch_top);
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index bd70d052e7..8ca75262c5 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -305,6 +305,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
oidset_init(&commits, 0);
if (opts.progress)
progress = start_delayed_progress(
+ the_repository,
_("Collecting commits from input"), 0);
while (strbuf_getline(&buf, stdin) != EOF) {
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index 2ca1a57ebb..38457600a4 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -119,8 +119,8 @@ int cmd_commit_tree(int argc,
git_config(git_default_config, NULL);
- if (argc < 2 || !strcmp(argv[1], "-h"))
- usage_with_options(commit_tree_usage, options);
+ show_usage_with_options_if_asked(argc, argv,
+ commit_tree_usage, options);
argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
diff --git a/builtin/commit.c b/builtin/commit.c
index ef5e622c07..2f45968222 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -44,7 +44,7 @@
#include "trailer.h"
static const char * const builtin_commit_usage[] = {
- N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n"
+ N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u[<mode>]] [--amend]\n"
" [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|reword):]<commit>]\n"
" [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n"
" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n"
@@ -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;
}
@@ -1559,8 +1561,8 @@ struct repository *repo UNUSED)
OPT_END(),
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_status_usage, builtin_status_options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_status_usage, builtin_status_options);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
@@ -1736,8 +1738,8 @@ int cmd_commit(int argc,
struct strbuf err = STRBUF_INIT;
int ret = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_commit_usage, builtin_commit_options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_commit_usage, builtin_commit_options);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
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/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index bc22f5c6d2..e707618e74 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -142,9 +142,9 @@ static void serve_one_client(FILE *in, FILE *out)
fprintf(out, "username=%s\n", e->item.username);
if (e->item.password)
fprintf(out, "password=%s\n", e->item.password);
- if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.authtype)
+ if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_RESPONSE) && e->item.authtype)
fprintf(out, "authtype=%s\n", e->item.authtype);
- if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.credential)
+ if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_RESPONSE) && e->item.credential)
fprintf(out, "credential=%s\n", e->item.credential);
if (e->item.password_expiry_utc != TIME_MAX)
fprintf(out, "password_expiry_utc=%"PRItime"\n",
diff --git a/builtin/credential.c b/builtin/credential.c
index 14c8c6608b..2e11b15dde 100644
--- a/builtin/credential.c
+++ b/builtin/credential.c
@@ -18,7 +18,8 @@ int cmd_credential(int argc,
git_config(git_default_config, NULL);
- if (argc != 2 || !strcmp(argv[1], "-h"))
+ show_usage_if_asked(argc, argv, usage_msg);
+ if (argc != 2)
usage(usage_msg);
op = argv[1];
@@ -32,15 +33,15 @@ int cmd_credential(int argc,
die("unable to read credential from stdin");
if (!strcmp(op, "fill")) {
- credential_fill(&c, 0);
+ credential_fill(the_repository, &c, 0);
credential_next_state(&c);
credential_write(&c, stdout, CREDENTIAL_OP_RESPONSE);
} else if (!strcmp(op, "approve")) {
credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER);
- credential_approve(&c);
+ credential_approve(the_repository, &c);
} else if (!strcmp(op, "reject")) {
credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER);
- credential_reject(&c);
+ credential_reject(the_repository, &c);
} else {
usage(usage_msg);
}
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index 66a22d918e..33c39bd598 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
@@ -58,7 +60,7 @@ int cmd_diagnose(int argc,
}
/* Prepare diagnostics */
- if (create_diagnostics_archive(&zip_path, mode))
+ if (create_diagnostics_archive(the_repository, &zip_path, mode))
die_errno(_("unable to create diagnostics archive %s"),
zip_path.buf);
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 604b04bb2c..99b1749723 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -29,8 +29,7 @@ int cmd_diff_files(int argc,
int result;
unsigned options = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(diff_files_usage);
+ show_usage_if_asked(argc, argv, diff_files_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index ebc824602e..81c0bc8ed7 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -26,8 +26,7 @@ int cmd_diff_index(int argc,
int i;
int result;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(diff_cache_usage);
+ show_usage_if_asked(argc, argv, diff_cache_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
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/diff-tree.c b/builtin/diff-tree.c
index 40804e7b48..e31cc797fe 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -122,8 +122,7 @@ int cmd_diff_tree(int argc,
int read_stdin = 0;
int merge_base = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(diff_tree_usage);
+ show_usage_if_asked(argc, argv, diff_tree_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 03a8bb92a9..41cd00066c 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -12,8 +12,6 @@
* Copyright (C) 2016 Johannes Schindelin
*/
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "builtin.h"
#include "abspath.h"
@@ -36,18 +34,27 @@
#include "entry.h"
#include "setup.h"
-static int trust_exit_code;
-
static const char *const builtin_difftool_usage[] = {
N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
NULL
};
+struct difftool_options {
+ int has_symlinks;
+ int symlinks;
+ int trust_exit_code;
+};
+
static int difftool_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
+ struct difftool_options *dt_options = (struct difftool_options *)cb;
if (!strcmp(var, "difftool.trustexitcode")) {
- trust_exit_code = git_config_bool(var, value);
+ dt_options->trust_exit_code = git_config_bool(var, value);
+ return 0;
+ }
+ if (!strcmp(var, "core.symlinks")) {
+ dt_options->has_symlinks = git_config_bool(var, value);
return 0;
}
@@ -63,7 +70,8 @@ static int print_tool_help(void)
return run_command(&cmd);
}
-static int parse_index_info(char *p, int *mode1, int *mode2,
+static int parse_index_info(struct repository *repo,
+ char *p, int *mode1, int *mode2,
struct object_id *oid1, struct object_id *oid2,
char *status)
{
@@ -75,11 +83,11 @@ static int parse_index_info(char *p, int *mode1, int *mode2,
*mode2 = (int)strtol(p + 1, &p, 8);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
- if (parse_oid_hex(++p, oid1, (const char **)&p))
+ if (parse_oid_hex_algop(++p, oid1, (const char **)&p, repo->hash_algo))
return error("expected object ID, got '%s'", p);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
- if (parse_oid_hex(++p, oid2, (const char **)&p))
+ if (parse_oid_hex_algop(++p, oid2, (const char **)&p, repo->hash_algo))
return error("expected object ID, got '%s'", p);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
@@ -106,7 +114,8 @@ static void add_path(struct strbuf *buf, size_t base_len, const char *path)
/*
* Determine whether we can simply reuse the file in the worktree.
*/
-static int use_wt_file(const char *workdir, const char *name,
+static int use_wt_file(struct repository *repo,
+ const char *workdir, const char *name,
struct object_id *oid)
{
struct strbuf buf = STRBUF_INIT;
@@ -121,7 +130,7 @@ static int use_wt_file(const char *workdir, const char *name,
int fd = open(buf.buf, O_RDONLY);
if (fd >= 0 &&
- !index_fd(the_repository->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
+ !index_fd(repo->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
if (is_null_oid(oid)) {
oidcpy(oid, &wt_oid);
use = 1;
@@ -212,13 +221,14 @@ static int path_entry_cmp(const void *cmp_data UNUSED,
return strcmp(a->path, key ? key : b->path);
}
-static void changed_files(struct hashmap *result, const char *index_path,
+static void changed_files(struct repository *repo,
+ struct hashmap *result, const char *index_path,
const char *workdir)
{
struct child_process update_index = CHILD_PROCESS_INIT;
struct child_process diff_files = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT;
- const char *git_dir = absolute_path(repo_get_git_dir(the_repository));
+ const char *git_dir = absolute_path(repo_get_git_dir(repo));
FILE *fp;
strvec_pushl(&update_index.args,
@@ -291,13 +301,15 @@ static int ensure_leading_directories(char *path)
* to compare the readlink(2) result as text, even on a filesystem that is
* capable of doing a symbolic link.
*/
-static char *get_symlink(const struct object_id *oid, const char *path)
+static char *get_symlink(struct repository *repo,
+ struct difftool_options *dt_options,
+ const struct object_id *oid, const char *path)
{
char *data;
if (is_null_oid(oid)) {
/* The symlink is unknown to Git so read from the filesystem */
struct strbuf link = STRBUF_INIT;
- if (has_symlinks) {
+ if (dt_options->has_symlinks) {
if (strbuf_readlink(&link, path, strlen(path)))
die(_("could not read symlink %s"), path);
} else if (strbuf_read_file(&link, path, 128))
@@ -307,8 +319,7 @@ static char *get_symlink(const struct object_id *oid, const char *path)
} else {
enum object_type type;
unsigned long size;
- data = repo_read_object_file(the_repository, oid, &type,
- &size);
+ data = repo_read_object_file(repo, oid, &type, &size);
if (!data)
die(_("could not read object %s for symlink %s"),
oid_to_hex(oid), path);
@@ -355,7 +366,9 @@ static void write_standin_files(struct pair_entry *entry,
write_file_in_directory(rdir, rdir_len, entry->path, entry->right);
}
-static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
+static int run_dir_diff(struct repository *repo,
+ struct difftool_options *dt_options,
+ const char *extcmd, const char *prefix,
struct child_process *child)
{
struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT;
@@ -375,7 +388,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL);
struct hashmap_iter iter;
struct pair_entry *entry;
- struct index_state wtindex = INDEX_STATE_INIT(the_repository);
+ struct index_state wtindex = INDEX_STATE_INIT(repo);
struct checkout lstate, rstate;
int err = 0;
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -383,7 +396,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap tmp_modified = HASHMAP_INIT(path_entry_cmp, NULL);
int indices_loaded = 0;
- workdir = repo_get_work_tree(the_repository);
+ workdir = repo_get_work_tree(repo);
/* Setup temp directories */
tmp = getenv("TMPDIR");
@@ -438,8 +451,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
"not supported in\n"
"directory diff mode ('-d' and '--dir-diff')."));
- if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid,
- &status))
+ if (parse_index_info(repo, info.buf, &lmode, &rmode, &loid, &roid, &status))
break;
if (strbuf_getline_nul(&lpath, fp))
break;
@@ -469,13 +481,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
}
if (S_ISLNK(lmode)) {
- char *content = get_symlink(&loid, src_path);
+ char *content = get_symlink(repo, dt_options, &loid, src_path);
add_left_or_right(&symlinks2, src_path, content, 0);
free(content);
}
if (S_ISLNK(rmode)) {
- char *content = get_symlink(&roid, dst_path);
+ char *content = get_symlink(repo, dt_options, &roid, dst_path);
add_left_or_right(&symlinks2, dst_path, content, 1);
free(content);
}
@@ -500,7 +512,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
}
hashmap_add(&working_tree_dups, &entry->entry);
- if (!use_wt_file(workdir, dst_path, &roid)) {
+ if (!use_wt_file(repo, workdir, dst_path, &roid)) {
if (checkout_path(rmode, &roid, dst_path,
&rstate)) {
ret = error("could not write '%s'",
@@ -528,7 +540,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
goto finish;
}
add_path(&wtdir, wtdir_len, dst_path);
- if (symlinks) {
+ if (dt_options->symlinks) {
if (symlink(wtdir.buf, rdir.buf)) {
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
goto finish;
@@ -614,7 +626,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
if (lstat(rdir.buf, &st))
continue;
- if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
+ if ((dt_options->symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
continue;
if (!indices_loaded) {
@@ -626,9 +638,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
ret = error("could not write %s", buf.buf);
goto finish;
}
- changed_files(&wt_modified, buf.buf, workdir);
+ changed_files(repo, &wt_modified, buf.buf, workdir);
strbuf_setlen(&rdir, rdir_len);
- changed_files(&tmp_modified, buf.buf, rdir.buf);
+ changed_files(repo, &tmp_modified, buf.buf, rdir.buf);
add_path(&rdir, rdir_len, name);
indices_loaded = 1;
}
@@ -702,11 +714,15 @@ static int run_file_diff(int prompt, const char *prefix,
int cmd_difftool(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
- int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
- tool_help = 0, no_index = 0;
+ int use_gui_tool = -1, dir_diff = 0, prompt = -1, tool_help = 0, no_index = 0;
static char *difftool_cmd = NULL, *extcmd = NULL;
+ struct difftool_options dt_options = {
+ .has_symlinks = 1,
+ .symlinks = 1,
+ .trust_exit_code = 0
+ };
struct option builtin_difftool_options[] = {
OPT_BOOL('g', "gui", &use_gui_tool,
N_("use `diff.guitool` instead of `diff.tool`")),
@@ -717,14 +733,14 @@ int cmd_difftool(int argc,
0, PARSE_OPT_NONEG),
OPT_SET_INT_F(0, "prompt", &prompt, NULL,
1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN),
- OPT_BOOL(0, "symlinks", &symlinks,
+ OPT_BOOL(0, "symlinks", &dt_options.symlinks,
N_("use symlinks in dir-diff mode")),
OPT_STRING('t', "tool", &difftool_cmd, N_("tool"),
N_("use the specified diff tool")),
OPT_BOOL(0, "tool-help", &tool_help,
N_("print a list of diff tools that may be used with "
"`--tool`")),
- OPT_BOOL(0, "trust-exit-code", &trust_exit_code,
+ OPT_BOOL(0, "trust-exit-code", &dt_options.trust_exit_code,
N_("make 'git-difftool' exit when an invoked diff "
"tool returns a non-zero exit code")),
OPT_STRING('x', "extcmd", &extcmd, N_("command"),
@@ -734,8 +750,9 @@ int cmd_difftool(int argc,
};
struct child_process child = CHILD_PROCESS_INIT;
- git_config(difftool_config, NULL);
- symlinks = has_symlinks;
+ if (repo)
+ repo_config(repo, difftool_config, &dt_options);
+ dt_options.symlinks = dt_options.has_symlinks;
argc = parse_options(argc, argv, prefix, builtin_difftool_options,
builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN_OPT |
@@ -749,8 +766,8 @@ int cmd_difftool(int argc,
if (!no_index){
setup_work_tree();
- setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);
- setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);
+ setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1);
+ setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1);
} else if (dir_diff)
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
@@ -783,7 +800,7 @@ int cmd_difftool(int argc,
}
setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE",
- trust_exit_code ? "true" : "false", 1);
+ dt_options.trust_exit_code ? "true" : "false", 1);
/*
* In directory diff mode, 'git-difftool--helper' is called once
@@ -799,6 +816,6 @@ int cmd_difftool(int argc,
strvec_pushv(&child.args, argv);
if (dir_diff)
- return run_dir_diff(extcmd, symlinks, prefix, &child);
+ return run_dir_diff(repo, &dt_options, extcmd, prefix, &child);
return run_file_diff(prompt, prefix, &child);
}
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 0f86392761..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;
@@ -798,8 +798,8 @@ static const char *create_index(void)
if (c != last)
die("internal consistency error creating the index");
- tmpfile = write_idx_file(NULL, idx, object_count, &pack_idx_opts,
- pack_data->hash);
+ tmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,
+ &pack_idx_opts, pack_data->hash);
free(idx);
return tmpfile;
}
@@ -878,9 +878,10 @@ static void end_packfile(void)
close_pack_windows(pack_data);
finalize_hashfile(pack_file, cur_pack_oid.hash, FSYNC_COMPONENT_PACK, 0);
- fixup_pack_header_footer(pack_data->pack_fd, pack_data->hash,
- pack_data->pack_name, object_count,
- cur_pack_oid.hash, pack_size);
+ fixup_pack_header_footer(the_hash_algo, pack_data->pack_fd,
+ pack_data->hash, pack_data->pack_name,
+ object_count, cur_pack_oid.hash,
+ pack_size);
if (object_count <= unpack_limit) {
if (!loosen_small_pack(pack_data)) {
@@ -953,15 +954,15 @@ static int store_object(
unsigned char hdr[96];
struct object_id oid;
unsigned long hdrlen, deltalen;
- git_hash_ctx c;
+ struct git_hash_ctx c;
git_zstream s;
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);
- the_hash_algo->final_oid_fn(&oid, &c);
+ git_hash_update(&c, hdr, hdrlen);
+ git_hash_update(&c, dat->buf, dat->len);
+ git_hash_final_oid(&oid, &c);
if (oidout)
oidcpy(oidout, &oid);
@@ -1095,7 +1096,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
struct object_id oid;
unsigned long hdrlen;
off_t offset;
- git_hash_ctx c;
+ struct git_hash_ctx c;
git_zstream s;
struct hashfile_checkpoint checkpoint;
int status = Z_OK;
@@ -1106,14 +1107,14 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
|| (pack_size + PACK_SIZE_THRESHOLD + len) < pack_size)
cycle_packfile();
- the_hash_algo->unsafe_init_fn(&checkpoint.ctx);
+ hashfile_checkpoint_init(pack_file, &checkpoint);
hashfile_checkpoint(pack_file, &checkpoint);
offset = checkpoint.offset;
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);
+ git_hash_update(&c, out_buf, hdrlen);
crc32_begin(pack_file);
@@ -1131,7 +1132,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
if (!n && feof(stdin))
die("EOF in data (%" PRIuMAX " bytes remaining)", len);
- the_hash_algo->update_fn(&c, in_buf, n);
+ git_hash_update(&c, in_buf, n);
s.next_in = in_buf;
s.avail_in = n;
len -= n;
@@ -1157,7 +1158,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
}
}
git_deflate_end(&s);
- the_hash_algo->final_oid_fn(&oid, &c);
+ git_hash_final_oid(&oid, &c);
if (oidout)
oidcpy(oidout, &oid);
@@ -2718,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;
@@ -2745,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();
@@ -2818,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))
@@ -3279,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,
@@ -3565,8 +3589,7 @@ int cmd_fast_import(int argc,
{
unsigned int i;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(fast_import_usage);
+ show_usage_if_asked(argc, argv, fast_import_usage);
reset_pack_idx_option(&pack_idx_opts);
git_pack_config();
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index bed2816c2d..d07eec9e55 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -75,6 +75,8 @@ int cmd_fetch_pack(int argc,
list_objects_filter_init(&args.filter_options);
args.uploadpack = "git-upload-pack";
+ show_usage_if_asked(argc, argv, fetch_pack_usage);
+
for (i = 1; i < argc && *argv[i] == '-'; i++) {
const char *arg = argv[i];
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fe2b26c74a..02af505469 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1617,13 +1617,13 @@ static void report_set_head(const char *remote, const char *head_name,
strbuf_release(&buf_prefix);
}
-static int set_head(const struct ref *remote_refs, int follow_remote_head,
- const char *no_warn_branch)
+static int set_head(const struct ref *remote_refs, struct remote *remote)
{
- int result = 0, create_only, is_bare, was_detached;
+ int result = 0, create_only, baremirror, was_detached;
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
b_local_head = STRBUF_INIT;
- const char *remote = gtransport->remote->name;
+ int follow_remote_head = remote->follow_remote_head;
+ const char *no_warn_branch = remote->no_warn_branch;
char *head_name = NULL;
struct ref *ref, *matches;
struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
@@ -1655,17 +1655,17 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (!head_name)
goto cleanup;
- is_bare = is_bare_repository();
- create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare;
- if (is_bare) {
+ baremirror = is_bare_repository() && remote->mirror;
+ create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !baremirror;
+ if (baremirror) {
strbuf_addstr(&b_head, "HEAD");
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
} else {
- strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
- strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
+ strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote->name);
+ strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote->name, head_name);
}
/* make sure it's valid */
- if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
+ if (!baremirror && !refs_ref_exists(refs, b_remote_head.buf)) {
result = 1;
goto cleanup;
}
@@ -1678,7 +1678,7 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (verbosity >= 0 &&
follow_remote_head == FOLLOW_REMOTE_WARN &&
(!no_warn_branch || strcmp(no_warn_branch, head_name)))
- report_set_head(remote, head_name, &b_local_head, was_detached);
+ report_set_head(remote->name, head_name, &b_local_head, was_detached);
cleanup:
free(head_name);
@@ -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);
@@ -1924,8 +1918,7 @@ static int do_fetch(struct transport *transport,
"you need to specify exactly one branch with the --set-upstream option"));
}
}
- if (set_head(remote_refs, transport->remote->follow_remote_head,
- transport->remote->no_warn_branch))
+ if (set_head(remote_refs, transport->remote))
;
/*
* Way too many cases where this can go wrong
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 715745a262..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");
@@ -108,7 +107,6 @@ int cmd_for_each_ref(int argc,
filter_and_format_refs(&filter, flags, sorting, &format);
ref_filter_clear(&filter);
- ref_format_clear(&format);
ref_sorting_release(sorting);
strvec_clear(&vec);
return 0;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 0196c54eb6..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
@@ -197,7 +198,8 @@ static int traverse_reachable(void)
unsigned int nr = 0;
int result = 0;
if (show_progress)
- progress = start_delayed_progress(_("Checking connectivity"), 0);
+ progress = start_delayed_progress(the_repository,
+ _("Checking connectivity"), 0);
while (pending.nr) {
result |= traverse_one_object(object_array_pop(&pending));
display_progress(progress, ++nr);
@@ -325,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;
@@ -703,7 +705,8 @@ static void fsck_object_dir(const char *path)
fprintf_ln(stderr, _("Checking object directory"));
if (show_progress)
- progress = start_progress(_("Checking object directories"), 256);
+ progress = start_progress(the_repository,
+ _("Checking object directories"), 256);
for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir,
&cb_data);
@@ -879,7 +882,8 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
if (show_progress) {
for (struct packed_git *p = get_all_packs(r); p; p = p->next)
pack_count++;
- progress = start_delayed_progress("Verifying reverse pack-indexes", pack_count);
+ progress = start_delayed_progress(the_repository,
+ "Verifying reverse pack-indexes", pack_count);
pack_count = 0;
}
@@ -902,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
};
@@ -925,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(),
};
@@ -967,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,
@@ -989,7 +1023,8 @@ int cmd_fsck(int argc,
total += p->num_objects;
}
- progress = start_progress(_("Checking objects"), total);
+ progress = start_progress(the_repository,
+ _("Checking objects"), total);
}
for (p = get_all_packs(the_repository); p;
p = p->next) {
@@ -1053,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
@@ -1061,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/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 029dc64d6c..0820e524f1 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -1598,8 +1598,8 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix UNUSED
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_fsmonitor__daemon_usage, options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_fsmonitor__daemon_usage, options);
die(_("fsmonitor--daemon not supported on this platform"));
}
diff --git a/builtin/gc.c b/builtin/gc.c
index a9b1c36de2..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);
}
}
@@ -139,6 +141,7 @@ struct gc_config {
char *prune_worktrees_expire;
char *repack_filter;
char *repack_filter_to;
+ char *repack_expire_to;
unsigned long big_pack_threshold;
unsigned long max_delta_cache_size;
/*
@@ -299,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;
@@ -445,7 +451,8 @@ static int keep_one_pack(struct string_list_item *item, void *data UNUSED)
static void add_repack_all_option(struct gc_config *cfg,
struct string_list *keep_pack)
{
- if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now"))
+ if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now")
+ && !(cfg->cruft_packs && cfg->repack_expire_to))
strvec_push(&repack, "-a");
else if (cfg->cruft_packs) {
strvec_push(&repack, "--cruft");
@@ -454,6 +461,8 @@ static void add_repack_all_option(struct gc_config *cfg,
if (cfg->max_cruft_size)
strvec_pushf(&repack, "--max-cruft-size=%lu",
cfg->max_cruft_size);
+ if (cfg->repack_expire_to)
+ strvec_pushf(&repack, "--expire-to=%s", cfg->repack_expire_to);
} else {
strvec_push(&repack, "-A");
if (cfg->prune_expire)
@@ -546,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) {
@@ -607,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)
@@ -688,7 +697,6 @@ struct repository *repo UNUSED)
const char *prune_expire_sentinel = "sentinel";
const char *prune_expire_arg = prune_expire_sentinel;
int ret;
-
struct option builtin_gc_options[] = {
OPT__QUIET(&quiet, N_("suppress progress reporting")),
{ OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"),
@@ -707,11 +715,13 @@ struct repository *repo UNUSED)
PARSE_OPT_NOCOMPLETE),
OPT_BOOL(0, "keep-largest-pack", &keep_largest_pack,
N_("repack all other packs except the largest pack")),
+ OPT_STRING(0, "expire-to", &cfg.repack_expire_to, N_("dir"),
+ N_("pack prefix to store a pack containing pruned objects")),
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_gc_usage, builtin_gc_options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_gc_usage, builtin_gc_options);
strvec_pushl(&reflog, "reflog", "expire", "--all", NULL);
strvec_pushl(&repack, "repack", "-d", "-l", NULL);
@@ -821,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);
@@ -887,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);
@@ -1909,7 +1923,7 @@ static int get_random_minute(void)
if (getenv("GIT_TEST_MAINT_SCHEDULER"))
return 13;
- return git_rand() % 60;
+ return git_rand(0) % 60;
}
static int is_launchctl_available(void)
diff --git a/builtin/get-tar-commit-id.c b/builtin/get-tar-commit-id.c
index 6bec0d1854..e4cd1627b4 100644
--- a/builtin/get-tar-commit-id.c
+++ b/builtin/get-tar-commit-id.c
@@ -13,7 +13,7 @@ static const char builtin_get_tar_commit_id_usage[] =
#define HEADERSIZE (2 * RECORDSIZE)
int cmd_get_tar_commit_id(int argc,
- const char **argv UNUSED,
+ const char **argv,
const char *prefix,
struct repository *repo UNUSED)
{
@@ -27,6 +27,8 @@ int cmd_get_tar_commit_id(int argc,
BUG_ON_NON_EMPTY_PREFIX(prefix);
+ show_usage_if_asked(argc, argv, builtin_get_tar_commit_id_usage);
+
if (argc != 1)
usage(builtin_get_tar_commit_id_usage);
diff --git a/builtin/grep.c b/builtin/grep.c
index d00ee76f24..d1427290f7 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1084,7 +1084,7 @@ int cmd_grep(int argc,
}
if (show_in_pager == default_pager)
- show_in_pager = git_pager(1);
+ show_in_pager = git_pager(the_repository, 1);
if (show_in_pager) {
opt.color = 0;
opt.name_only = 1;
@@ -1246,7 +1246,7 @@ int cmd_grep(int argc,
}
if (!show_in_pager && !opt.status_only)
- setup_pager();
+ setup_pager(the_repository);
die_for_incompatible_opt3(!use_index, "--no-index",
untracked, "--untracked",
diff --git a/builtin/help.c b/builtin/help.c
index 05136279cf..c257079ceb 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -658,7 +658,7 @@ int cmd_help(int argc,
case HELP_ACTION_ALL:
opt_mode_usage(argc, "--all", help_format);
if (verbose) {
- setup_pager();
+ setup_pager(the_repository);
list_all_cmds_help(show_external_commands,
show_aliases);
return 0;
@@ -692,7 +692,7 @@ int cmd_help(int argc,
return 0;
case HELP_ACTION_CONFIG:
opt_mode_usage(argc, "--config", help_format);
- setup_pager();
+ setup_pager(the_repository);
list_config_help(SHOW_CONFIG_HUMAN);
printf("\n%s\n", _("'git help config' for more information"));
return 0;
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 0b62b2589f..52cc97d52c 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -151,7 +151,7 @@ static unsigned int input_offset, input_len;
static off_t consumed_bytes;
static off_t max_input_size;
static unsigned deepest_delta;
-static git_hash_ctx input_ctx;
+static struct git_hash_ctx input_ctx;
static uint32_t input_crc32;
static int input_fd, output_fd;
static const char *curr_pack;
@@ -282,7 +282,8 @@ static unsigned check_objects(void)
max = get_max_object_index();
if (verbose)
- progress = start_delayed_progress(_("Checking objects"), max);
+ progress = start_delayed_progress(the_repository,
+ _("Checking objects"), max);
for (i = 0; i < max; i++) {
foreign_nr += check_object(get_indexed_object(i));
@@ -300,7 +301,7 @@ static void flush(void)
if (input_offset) {
if (output_fd >= 0)
write_or_die(output_fd, input_buffer, input_offset);
- the_hash_algo->update_fn(&input_ctx, input_buffer, input_offset);
+ git_hash_update(&input_ctx, input_buffer, input_offset);
memmove(input_buffer, input_buffer + input_offset, input_len);
input_offset = 0;
}
@@ -379,16 +380,18 @@ static const char *open_pack_file(const char *pack_name)
static void parse_pack_header(void)
{
- struct pack_header *hdr = fill(sizeof(struct pack_header));
+ unsigned char *hdr = fill(sizeof(struct pack_header));
/* Header consistency check */
- if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
+ if (get_be32(hdr) != PACK_SIGNATURE)
die(_("pack signature mismatch"));
- if (!pack_version_ok(hdr->hdr_version))
+ hdr += 4;
+ if (!pack_version_ok_native(get_be32(hdr)))
die(_("pack version %"PRIu32" unsupported"),
- ntohl(hdr->hdr_version));
+ get_be32(hdr));
+ hdr += 4;
- nr_objects = ntohl(hdr->hdr_entries);
+ nr_objects = get_be32(hdr);
use(sizeof(struct pack_header));
}
@@ -472,14 +475,14 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
int status;
git_zstream stream;
void *buf;
- git_hash_ctx c;
+ struct git_hash_ctx c;
char hdr[32];
int hdrlen;
if (!is_delta_type(type)) {
hdrlen = format_object_header(hdr, sizeof(hdr), type, size);
the_hash_algo->init_fn(&c);
- the_hash_algo->update_fn(&c, hdr, hdrlen);
+ git_hash_update(&c, hdr, hdrlen);
} else
oid = NULL;
if (type == OBJ_BLOB && size > big_file_threshold)
@@ -499,7 +502,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
status = git_inflate(&stream, 0);
use(input_len - stream.avail_in);
if (oid)
- the_hash_algo->update_fn(&c, last_out, stream.next_out - last_out);
+ git_hash_update(&c, last_out, stream.next_out - last_out);
if (buf == fixed_buf) {
stream.next_out = buf;
stream.avail_out = sizeof(fixed_buf);
@@ -509,7 +512,7 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
bad_object(offset, _("inflate returned %d"), status);
git_inflate_end(&stream);
if (oid)
- the_hash_algo->final_oid_fn(oid, &c);
+ git_hash_final_oid(oid, &c);
return buf == fixed_buf ? NULL : buf;
}
@@ -1245,10 +1248,11 @@ static void parse_pack_objects(unsigned char *hash)
struct ofs_delta_entry *ofs_delta = ofs_deltas;
struct object_id ref_delta_oid;
struct stat st;
- git_hash_ctx tmp_ctx;
+ struct git_hash_ctx tmp_ctx;
if (verbose)
progress = start_progress(
+ the_repository,
progress_title ? progress_title :
from_stdin ? _("Receiving objects") : _("Indexing objects"),
nr_objects);
@@ -1282,9 +1286,8 @@ static void parse_pack_objects(unsigned char *hash)
/* Check pack integrity */
flush();
- the_hash_algo->init_fn(&tmp_ctx);
- the_hash_algo->clone_fn(&tmp_ctx, &input_ctx);
- the_hash_algo->final_fn(hash, &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))
die(_("pack is corrupted (SHA1 mismatch)"));
use(the_hash_algo->rawsz);
@@ -1329,7 +1332,8 @@ static void resolve_deltas(struct pack_idx_option *opts)
QSORT(ref_deltas, nr_ref_deltas, compare_ref_delta_entry);
if (verbose || show_resolving_progress)
- progress = start_progress(_("Resolving deltas"),
+ progress = start_progress(the_repository,
+ _("Resolving deltas"),
nr_ref_deltas + nr_ofs_deltas);
nr_dispatched = 0;
@@ -1387,7 +1391,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
strbuf_release(&msg);
finalize_hashfile(f, tail_hash, FSYNC_COMPONENT_PACK, 0);
hashcpy(read_hash, pack_hash, the_repository->hash_algo);
- fixup_pack_header_footer(output_fd, pack_hash,
+ fixup_pack_header_footer(the_hash_algo, output_fd, pack_hash,
curr_pack, nr_objects,
read_hash, consumed_bytes-the_hash_algo->rawsz);
if (!hasheq(read_hash, tail_hash, the_repository->hash_algo))
@@ -1897,8 +1901,7 @@ int cmd_index_pack(int argc,
*/
fetch_if_missing = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(index_pack_usage);
+ show_usage_if_asked(argc, argv, index_pack_usage);
disable_replace_refs();
fsck_options.walk = mark_link;
@@ -1954,19 +1957,11 @@ int cmd_index_pack(int argc,
warning(_("no threads support, ignoring %s"), arg);
nr_threads = 1;
}
- } else if (starts_with(arg, "--pack_header=")) {
- struct pack_header *hdr;
- char *c;
-
- hdr = (struct pack_header *)input_buffer;
- hdr->hdr_signature = htonl(PACK_SIGNATURE);
- hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
- if (*c != ',')
- die(_("bad %s"), arg);
- hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
- if (*c)
- die(_("bad %s"), arg);
- input_len = sizeof(*hdr);
+ } else if (skip_prefix(arg, "--pack_header=", &arg)) {
+ if (parse_pack_header_option(arg,
+ input_buffer,
+ &input_len) < 0)
+ die(_("bad --pack_header: %s"), arg);
} else if (!strcmp(arg, "-v")) {
verbose = 1;
} else if (!strcmp(arg, "--progress-title")) {
@@ -2093,11 +2088,12 @@ int cmd_index_pack(int argc,
ALLOC_ARRAY(idx_objects, nr_objects);
for (i = 0; i < nr_objects; i++)
idx_objects[i] = &objects[i].idx;
- curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
+ curr_index = write_idx_file(the_hash_algo, index_name, idx_objects,
+ nr_objects, &opts, pack_hash);
if (rev_index)
- curr_rev_index = write_rev_file(rev_index_name, idx_objects,
- nr_objects, pack_hash,
- opts.flags);
+ curr_rev_index = write_rev_file(the_hash_algo, rev_index_name,
+ idx_objects, nr_objects,
+ pack_hash, opts.flags);
free(idx_objects);
if (!verify)
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 75e1b34123..04a6ef97bc 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -6,7 +6,6 @@
*/
#define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
#include "builtin.h"
#include "abspath.h"
@@ -209,7 +208,6 @@ static void cmd_log_init_defaults(struct rev_info *rev,
static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
{
- int i;
char *value = NULL;
struct string_list *include = decoration_filter->include_ref_pattern;
const struct string_list *config_exclude;
@@ -243,7 +241,7 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f
* No command-line or config options were given, so
* populate with sensible defaults.
*/
- for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
+ for (size_t i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
if (!ref_namespace[i].decoration)
continue;
@@ -369,7 +367,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
if (rev->line_level_traverse)
line_log_init(rev, line_cb.prefix, &line_cb.args);
- setup_pager();
+ setup_pager(the_repository);
}
static void cmd_log_init(int argc, const char **argv, const char *prefix,
@@ -717,14 +715,14 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
unsigned long size;
enum object_type type;
char *buf = repo_read_object_file(the_repository, oid, &type, &size);
- int offset = 0;
+ unsigned long offset = 0;
if (!buf)
return error(_("could not read object %s"), oid_to_hex(oid));
assert(type == OBJ_TAG);
while (offset < size && buf[offset] != '\n') {
- int new_offset = offset + 1;
+ unsigned long new_offset = offset + 1;
const char *ident;
while (new_offset < size && buf[new_offset++] != '\n')
; /* do nothing */
@@ -1316,24 +1314,25 @@ static void print_signature(const char *signature, FILE *file)
static char *find_branch_name(struct rev_info *rev)
{
- int i, positive = -1;
struct object_id branch_oid;
const struct object_id *tip_oid;
const char *ref, *v;
char *full_ref, *branch = NULL;
+ int interesting_found = 0;
+ size_t idx;
- for (i = 0; i < rev->cmdline.nr; i++) {
+ for (size_t i = 0; i < rev->cmdline.nr; i++) {
if (rev->cmdline.rev[i].flags & UNINTERESTING)
continue;
- if (positive < 0)
- positive = i;
- else
+ if (interesting_found)
return NULL;
+ interesting_found = 1;
+ idx = i;
}
- if (positive < 0)
+ if (!interesting_found)
return NULL;
- ref = rev->cmdline.rev[positive].name;
- tip_oid = &rev->cmdline.rev[positive].item->oid;
+ ref = rev->cmdline.rev[idx].name;
+ tip_oid = &rev->cmdline.rev[idx].item->oid;
if (repo_dwim_ref(the_repository, ref, strlen(ref), &branch_oid,
&full_ref, 0) &&
skip_prefix(full_ref, "refs/heads/", &v) &&
@@ -1746,11 +1745,12 @@ struct base_tree_info {
static struct commit *get_base_commit(const struct format_config *cfg,
struct commit **list,
- int total)
+ size_t total)
{
struct commit *base = NULL;
struct commit **rev;
- int i = 0, rev_nr = 0, auto_select, die_on_failure, ret;
+ int auto_select, die_on_failure, ret;
+ size_t i = 0, rev_nr = 0;
switch (cfg->auto_base) {
case AUTO_BASE_NEVER:
@@ -1885,13 +1885,12 @@ define_commit_slab(commit_base, int);
static void prepare_bases(struct base_tree_info *bases,
struct commit *base,
struct commit **list,
- int total)
+ size_t total)
{
struct commit *commit;
struct rev_info revs;
struct diff_options diffopt;
struct commit_base commit_base;
- int i;
if (!base)
return;
@@ -1906,7 +1905,7 @@ static void prepare_bases(struct base_tree_info *bases,
repo_init_revisions(the_repository, &revs, NULL);
revs.max_parents = 1;
revs.topo_order = 1;
- for (i = 0; i < total; i++) {
+ for (size_t i = 0; i < total; i++) {
list[i]->object.flags &= ~UNINTERESTING;
add_pending_object(&revs, &list[i]->object, "rev_list");
*commit_base_at(&commit_base, list[i]) = 1;
@@ -2007,7 +2006,7 @@ int cmd_format_patch(int argc,
struct rev_info rev;
char *to_free = NULL;
struct setup_revision_opt s_r_opt;
- int nr = 0, total, i;
+ size_t nr = 0, total, i;
int use_stdout = 0;
int start_number = -1;
int just_numbers = 0;
@@ -2183,7 +2182,7 @@ int cmd_format_patch(int argc,
fmt_patch_suffix = cfg.fmt_patch_suffix;
/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
- if (cfg.log.fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
+ if (cfg.log.fmt_patch_name_max <= cast_size_t_to_int(strlen("0000-") + strlen(fmt_patch_suffix)))
cfg.log.fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
if (cover_from_description_arg)
@@ -2296,7 +2295,7 @@ int cmd_format_patch(int argc,
rev.commit_format = CMIT_FMT_MBOXRD;
if (use_stdout) {
- setup_pager();
+ setup_pager(the_repository);
} else if (!rev.diffopt.close_file) {
int saved;
@@ -2310,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:
@@ -2320,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);
@@ -2499,12 +2498,16 @@ int cmd_format_patch(int argc,
rev.add_signoff = cfg.do_signoff;
if (show_progress)
- progress = start_delayed_progress(_("Generating patches"), total);
- while (0 <= --nr) {
+ progress = start_delayed_progress(the_repository,
+ _("Generating patches"), total);
+ for (i = 0; i < nr; i++) {
+ size_t idx = nr - i - 1;
int shown;
- display_progress(progress, total - nr);
- commit = list[nr];
- rev.nr = total - nr + (start_number - 1);
+
+ display_progress(progress, total - idx);
+ commit = list[idx];
+ rev.nr = total - idx + (start_number - 1);
+
/* Make the second and subsequent mails replies to the first */
if (cfg.thread) {
/* Have we already had a message ID? */
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 15499cd12b..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;
@@ -644,18 +644,18 @@ int cmd_ls_files(int argc,
};
int ret = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(ls_files_usage, builtin_ls_files_options);
+ 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/mailinfo.c b/builtin/mailinfo.c
index e17dec27b1..8de7ba7de1 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -83,7 +83,7 @@ int cmd_mailinfo(int argc,
OPT_END()
};
- setup_mailinfo(&mi);
+ setup_mailinfo(the_repository, &mi);
meta_charset.policy = CHARSET_DEFAULT;
argc = parse_options(argc, argv, prefix, options, mailinfo_usage, 0);
diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c
index 41dd304731..264df6259a 100644
--- a/builtin/mailsplit.c
+++ b/builtin/mailsplit.c
@@ -284,6 +284,8 @@ int cmd_mailsplit(int argc,
BUG_ON_NON_EMPTY_PREFIX(prefix);
+ show_usage_if_asked(argc, argv, git_mailsplit_usage);
+
for (argp = argv+1; *argp; argp++) {
const char *arg = *argp;
@@ -297,8 +299,6 @@ int cmd_mailsplit(int argc,
continue;
} else if ( arg[1] == 'f' ) {
nr = strtol(arg+2, NULL, 10);
- } else if ( arg[1] == 'h' ) {
- usage(git_mailsplit_usage);
} else if ( arg[1] == 'b' && !arg[2] ) {
allow_bare = 1;
} else if (!strcmp(arg, "--keep-cr")) {
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index a20c93b11a..123c81515e 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -8,7 +8,7 @@
#include "parse-options.h"
#include "commit-reach.h"
-static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
+static int show_merge_base(struct commit **rev, size_t rev_nr, int show_all)
{
struct commit_list *result = NULL, *r;
@@ -149,7 +149,7 @@ int cmd_merge_base(int argc,
struct repository *repo UNUSED)
{
struct commit **rev;
- int rev_nr = 0;
+ size_t rev_nr = 0;
int show_all = 0;
int cmdmode = 0;
int ret;
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 342699edb7..3314fb1336 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -75,6 +75,9 @@ static void merge_all(void)
}
}
+static const char usage_string[] =
+"git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])";
+
int cmd_merge_index(int argc,
const char **argv,
const char *prefix UNUSED,
@@ -87,8 +90,10 @@ int cmd_merge_index(int argc,
*/
signal(SIGCHLD, SIG_DFL);
+ show_usage_if_asked(argc, argv, usage_string);
+
if (argc < 3)
- usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
+ usage(usage_string);
repo_read_index(the_repository);
diff --git a/builtin/merge-ours.c b/builtin/merge-ours.c
index 3ecd9172f1..97b8a792c7 100644
--- a/builtin/merge-ours.c
+++ b/builtin/merge-ours.c
@@ -23,8 +23,7 @@ int cmd_merge_ours(int argc,
const char *prefix UNUSED,
struct repository *repo UNUSED)
{
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(builtin_merge_ours_usage);
+ show_usage_if_asked(argc, argv, builtin_merge_ours_usage);
/*
* The contents of the current index becomes the tree we
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 1dd295558b..abfc060e28 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -38,6 +38,12 @@ int cmd_merge_recursive(int argc,
if (argv[0] && ends_with(argv[0], "-subtree"))
o.subtree_shift = "";
+ if (argc == 2 && !strcmp(argv[1], "-h")) {
+ struct strbuf msg = STRBUF_INIT;
+ strbuf_addf(&msg, builtin_merge_recursive_usage, argv[0]);
+ show_usage_if_asked(argc, argv, msg.buf);
+ }
+
if (argc < 4)
usagef(builtin_merge_recursive_usage, argv[0]);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 9a6c8b4e4c..3ec7127b3a 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -18,6 +18,7 @@
#include "tree.h"
#include "config.h"
#include "strvec.h"
+#include "write-or-die.h"
static int line_termination = '\n';
@@ -575,7 +576,7 @@ int cmd_merge_tree(int argc,
};
/* Init merge options */
- init_ui_merge_options(&o.merge_options, the_repository);
+ init_basic_merge_options(&o.merge_options, the_repository);
/* Parse arguments */
original_argc = argc - 1; /* ignoring argv[0] */
@@ -600,7 +601,6 @@ int cmd_merge_tree(int argc,
line_termination = '\0';
while (strbuf_getline_lf(&buf, stdin) != EOF) {
struct strbuf **split;
- int result;
const char *input_merge_base = NULL;
split = strbuf_split(&buf, ' ');
@@ -617,15 +617,14 @@ int cmd_merge_tree(int argc,
if (input_merge_base && split[2] && split[3] && !split[4]) {
strbuf_rtrim(split[2]);
strbuf_rtrim(split[3]);
- result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
+ real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
} else if (!input_merge_base && !split[2]) {
- result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
+ real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
} else {
die(_("malformed input line: '%s'."), buf.buf);
}
+ maybe_flush_or_die(stdout, "stdout");
- if (result < 0)
- die(_("merging cannot continue; got unclean result of %d"), result);
strbuf_list_free(split);
}
strbuf_release(&buf);
diff --git a/builtin/merge.c b/builtin/merge.c
index 5f67007bba..ba9faf126a 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1300,8 +1300,8 @@ int cmd_merge(int argc,
void *branch_to_free;
int orig_argc = argc;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_merge_usage, builtin_merge_options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_merge_usage, builtin_merge_options);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
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 1c3b842651..79e1e6fb52 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;
@@ -269,6 +270,43 @@ struct configured_exclusion {
static struct oidmap configured_exclusions;
static struct oidset excluded_by_config;
+static int name_hash_version = -1;
+
+/**
+ * Check whether the name_hash_version chosen by user input is appropriate,
+ * and also validate whether it is compatible with other features.
+ */
+static void validate_name_hash_version(void)
+{
+ if (name_hash_version < 1 || name_hash_version > 2)
+ die(_("invalid --name-hash-version option: %d"), name_hash_version);
+ if (write_bitmap_index && name_hash_version != 1) {
+ warning(_("currently, --write-bitmap-index requires --name-hash-version=1"));
+ name_hash_version = 1;
+ }
+}
+
+static inline uint32_t pack_name_hash_fn(const char *name)
+{
+ static int seen_version = -1;
+
+ if (seen_version < 0)
+ seen_version = name_hash_version;
+ else if (seen_version != name_hash_version)
+ BUG("name hash version changed from %d to %d mid-process",
+ seen_version, name_hash_version);
+
+ switch (name_hash_version) {
+ case 1:
+ return pack_name_hash(name);
+
+ case 2:
+ return pack_name_hash_v2((const unsigned char *)name);
+
+ default:
+ BUG("invalid name-hash version: %d", name_hash_version);
+ }
+}
/*
* stats
@@ -1264,7 +1302,8 @@ static void write_pack_file(void)
struct object_entry **write_order;
if (progress > pack_to_stdout)
- progress_state = start_progress(_("Writing objects"), nr_result);
+ progress_state = start_progress(the_repository,
+ _("Writing objects"), nr_result);
ALLOC_ARRAY(written_list, to_pack.nr_objects);
write_order = compute_write_order();
@@ -1318,8 +1357,9 @@ static void write_pack_file(void)
*/
int fd = finalize_hashfile(f, hash, FSYNC_COMPONENT_PACK, 0);
- fixup_pack_header_footer(fd, hash, pack_tmp_name,
- nr_written, hash, offset);
+ fixup_pack_header_footer(the_hash_algo, fd, hash,
+ pack_tmp_name, nr_written,
+ hash, offset);
close(fd);
if (write_bitmap_index) {
if (write_bitmap_index != WRITE_BITMAP_QUIET)
@@ -1367,9 +1407,10 @@ static void write_pack_file(void)
if (cruft)
pack_idx_opts.flags |= WRITE_MTIMES;
- stage_tmp_packfiles(&tmpname, pack_tmp_name,
- written_list, nr_written,
- &to_pack, &pack_idx_opts, hash,
+ stage_tmp_packfiles(the_hash_algo, &tmpname,
+ pack_tmp_name, written_list,
+ nr_written, &to_pack,
+ &pack_idx_opts, hash,
&idx_tmp_name);
if (write_bitmap_index) {
@@ -1462,8 +1503,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;
@@ -1513,12 +1606,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;
+ }
}
/*
@@ -1537,7 +1647,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;
@@ -1553,7 +1664,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;
}
@@ -1567,10 +1678,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;
@@ -1585,7 +1697,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;
@@ -1596,7 +1709,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;
}
@@ -1604,7 +1717,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));
@@ -1634,6 +1747,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,
@@ -1686,7 +1808,7 @@ static int add_object_entry(const struct object_id *oid, enum object_type type,
return 0;
}
- create_object_entry(oid, type, pack_name_hash(name),
+ create_object_entry(oid, type, pack_name_hash_fn(name),
exclude, name && no_try_delta(name),
found_pack, found_offset);
return 1;
@@ -1900,7 +2022,7 @@ static void add_preferred_base_object(const char *name)
{
struct pbase_tree *it;
size_t cmplen;
- unsigned hash = pack_name_hash(name);
+ unsigned hash = pack_name_hash_fn(name);
if (!num_preferred_base || check_pbase_path(hash))
return;
@@ -2400,7 +2522,8 @@ static void get_object_details(void)
struct object_entry **sorted_by_offset;
if (progress)
- progress_state = start_progress(_("Counting objects"),
+ progress_state = start_progress(the_repository,
+ _("Counting objects"),
to_pack.nr_objects);
CALLOC_ARRAY(sorted_by_offset, to_pack.nr_objects);
@@ -3220,7 +3343,8 @@ static void prepare_pack(int window, int depth)
unsigned nr_done = 0;
if (progress)
- progress_state = start_progress(_("Compressing objects"),
+ progress_state = start_progress(the_repository,
+ _("Compressing objects"),
nr_deltas);
QSORT(delta_list, n, type_size_sort);
ll_find_deltas(delta_list, n, window+1, depth, &nr_done);
@@ -3410,7 +3534,7 @@ static void show_object_pack_hint(struct object *object, const char *name,
* here using a now in order to perhaps improve the delta selection
* process.
*/
- oe->hash = pack_name_hash(name);
+ oe->hash = pack_name_hash_fn(name);
oe->no_try_delta = name && no_try_delta(name);
stdin_packs_hints_nr++;
@@ -3560,11 +3684,11 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
entry = packlist_find(&to_pack, oid);
if (entry) {
if (name) {
- entry->hash = pack_name_hash(name);
+ entry->hash = pack_name_hash_fn(name);
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)) {
/*
@@ -3583,7 +3707,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
return;
}
- entry = create_object_entry(oid, type, pack_name_hash(name),
+ entry = create_object_entry(oid, type, pack_name_hash_fn(name),
0, name && no_try_delta(name),
pack, offset);
}
@@ -3638,6 +3762,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;
}
}
@@ -3648,7 +3774,8 @@ static void add_objects_in_unpacked_packs(void);
static void enumerate_cruft_objects(void)
{
if (progress)
- progress_state = start_progress(_("Enumerating cruft objects"), 0);
+ progress_state = start_progress(the_repository,
+ _("Enumerating cruft objects"), 0);
add_objects_in_unpacked_packs();
add_unreachable_loose_objects();
@@ -3674,7 +3801,8 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs
revs.ignore_missing_links = 1;
if (progress)
- progress_state = start_progress(_("Enumerating cruft objects"), 0);
+ progress_state = start_progress(the_repository,
+ _("Enumerating cruft objects"), 0);
ret = add_unseen_recent_objects_to_traversal(&revs, cruft_expiration,
set_cruft_mtime, 1);
stop_progress(&progress_state);
@@ -3693,7 +3821,8 @@ static void enumerate_and_traverse_cruft_objects(struct string_list *fresh_packs
if (prepare_revision_walk(&revs))
die(_("revision walk setup failed"));
if (progress)
- progress_state = start_progress(_("Traversing cruft objects"), 0);
+ progress_state = start_progress(the_repository,
+ _("Traversing cruft objects"), 0);
nr_seen = 0;
traverse_commit_list(&revs, show_cruft_commit, show_cruft_object, NULL);
@@ -4060,6 +4189,15 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
if (!(bitmap_git = prepare_bitmap_walk(revs, 0)))
return -1;
+ /*
+ * For now, force the name-hash version to be 1 since that
+ * is the version implied by the bitmap format. Later, the
+ * format can include this version explicitly in its format,
+ * allowing readers to know the version that was used during
+ * the bitmap write.
+ */
+ name_hash_version = 1;
+
if (pack_options_allow_reuse())
reuse_partial_packfile_from_bitmap(bitmap_git,
&reuse_packfiles,
@@ -4435,6 +4573,8 @@ int cmd_pack_objects(int argc,
OPT_STRING_LIST(0, "uri-protocol", &uri_protocols,
N_("protocol"),
N_("exclude any configured uploadpack.blobpackfileuri with this protocol")),
+ OPT_INTEGER(0, "name-hash-version", &name_hash_version,
+ N_("use the specified name-hash function to group similar objects")),
OPT_END(),
};
@@ -4590,6 +4730,11 @@ int cmd_pack_objects(int argc,
if (pack_to_stdout || !rev_list_all)
write_bitmap_index = 0;
+ if (name_hash_version < 0)
+ name_hash_version = (int)git_env_ulong("GIT_TEST_NAME_HASH_VERSION", 1);
+
+ validate_name_hash_version();
+
if (use_delta_islands)
strvec_push(&rp, "--topo-order");
@@ -4625,7 +4770,8 @@ int cmd_pack_objects(int argc,
prepare_packing_data(the_repository, &to_pack);
if (progress && !cruft)
- progress_state = start_progress(_("Enumerating objects"), 0);
+ progress_state = start_progress(the_repository,
+ _("Enumerating objects"), 0);
if (stdin_packs) {
/* avoids adding objects in excluded packs */
ignore_packed_keep_in_core = 1;
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index e046575871..3febe732f8 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -595,8 +595,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
struct strbuf idx_name = STRBUF_INIT;
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(pack_redundant_usage);
+ show_usage_if_asked(argc, argv, pack_redundant_usage);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
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/patch-id.c b/builtin/patch-id.c
index f540d8daa7..cdef2ec10a 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -70,7 +70,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu
int before = -1, after = -1;
int diff_is_binary = 0;
char pre_oid_str[GIT_MAX_HEXSZ + 1], post_oid_str[GIT_MAX_HEXSZ + 1];
- git_hash_ctx ctx;
+ struct git_hash_ctx ctx;
the_hash_algo->init_fn(&ctx);
oidclr(result, the_repository->hash_algo);
@@ -85,7 +85,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu
!skip_prefix(line, "From ", &p) &&
starts_with(line, "\\ ") && 12 < strlen(line)) {
if (verbatim)
- the_hash_algo->update_fn(&ctx, line, strlen(line));
+ git_hash_update(&ctx, line, strlen(line));
continue;
}
@@ -104,10 +104,10 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu
starts_with(line, "Binary files")) {
diff_is_binary = 1;
before = 0;
- the_hash_algo->update_fn(&ctx, pre_oid_str,
- strlen(pre_oid_str));
- the_hash_algo->update_fn(&ctx, post_oid_str,
- strlen(post_oid_str));
+ git_hash_update(&ctx, pre_oid_str,
+ strlen(pre_oid_str));
+ git_hash_update(&ctx, post_oid_str,
+ strlen(post_oid_str));
if (stable)
flush_one_hunk(result, &ctx);
continue;
@@ -165,7 +165,7 @@ static size_t get_one_patchid(struct object_id *next_oid, struct object_id *resu
/* Add line to hash algo (possibly removing whitespace) */
len = verbatim ? strlen(line) : remove_space(line);
patchlen += len;
- the_hash_algo->update_fn(&ctx, line, len);
+ git_hash_update(&ctx, line, len);
}
if (!found_next)
diff --git a/builtin/prune.c b/builtin/prune.c
index aeff9ca1b3..1c357fffd8 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -64,7 +64,8 @@ static void perform_reachability_traversal(struct rev_info *revs)
return;
if (show_progress)
- progress = start_delayed_progress(_("Checking connectivity"), 0);
+ progress = start_delayed_progress(the_repository,
+ _("Checking connectivity"), 0);
mark_reachable_objects(revs, 1, expire, progress);
stop_progress(&progress);
initialized = 1;
diff --git a/builtin/push.c b/builtin/push.c
index 90de3746b5..92d530e5c4 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -78,7 +78,7 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref,
.src = matched->name,
};
- if (!query_refspecs(&remote->push, &query) && query.dst) {
+ if (!refspec_find_match(&remote->push, &query) && query.dst) {
refspec_appendf(refspec, "%s%s:%s",
query.force ? "+" : "",
query.src, query.dst);
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 0498fff3c9..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) {
@@ -1223,9 +1223,9 @@ int cmd_rebase(int argc,
};
int i;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_rebase_usage,
- builtin_rebase_options);
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_rebase_usage,
+ builtin_rebase_options);
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c2e9103f11..7b28fc9df6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -174,7 +174,7 @@ static int receive_pack_config(const char *var, const char *value,
char *path;
if (git_config_pathname(&path, var, value))
- return 1;
+ return -1;
strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
fsck_msg_types.len ? ',' : '=', path);
free(path);
@@ -566,14 +566,14 @@ static void hmac_hash(unsigned char *out,
unsigned char k_ipad[GIT_MAX_BLKSZ];
unsigned char k_opad[GIT_MAX_BLKSZ];
int i;
- git_hash_ctx ctx;
+ struct git_hash_ctx ctx;
/* RFC 2104 2. (1) */
memset(key, '\0', GIT_MAX_BLKSZ);
if (the_hash_algo->blksz < key_len) {
the_hash_algo->init_fn(&ctx);
- the_hash_algo->update_fn(&ctx, key_in, key_len);
- the_hash_algo->final_fn(key, &ctx);
+ git_hash_update(&ctx, key_in, key_len);
+ git_hash_final(key, &ctx);
} else {
memcpy(key, key_in, key_len);
}
@@ -586,15 +586,15 @@ static void hmac_hash(unsigned char *out,
/* RFC 2104 2. (3) & (4) */
the_hash_algo->init_fn(&ctx);
- the_hash_algo->update_fn(&ctx, k_ipad, sizeof(k_ipad));
- the_hash_algo->update_fn(&ctx, text, text_len);
- the_hash_algo->final_fn(out, &ctx);
+ git_hash_update(&ctx, k_ipad, sizeof(k_ipad));
+ git_hash_update(&ctx, text, text_len);
+ git_hash_final(out, &ctx);
/* RFC 2104 2. (6) & (7) */
the_hash_algo->init_fn(&ctx);
- the_hash_algo->update_fn(&ctx, k_opad, sizeof(k_opad));
- the_hash_algo->update_fn(&ctx, out, the_hash_algo->rawsz);
- the_hash_algo->final_fn(out, &ctx);
+ git_hash_update(&ctx, k_opad, sizeof(k_opad));
+ git_hash_update(&ctx, out, the_hash_algo->rawsz);
+ git_hash_final(out, &ctx);
}
static char *prepare_push_cert_nonce(const char *path, timestamp_t stamp)
@@ -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;
}
@@ -2239,7 +2241,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
strvec_push(&child.args, alt_shallow_file);
}
- tmp_objdir = tmp_objdir_create("incoming");
+ tmp_objdir = tmp_objdir_create(the_repository, "incoming");
if (!tmp_objdir) {
if (err_fd > 0)
close(err_fd);
@@ -2304,7 +2306,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
if (status)
return "index-pack fork failed";
- lockfile = index_pack_lockfile(child.out, NULL);
+ lockfile = index_pack_lockfile(the_repository, child.out, NULL);
if (lockfile) {
pack_lockfile = register_tempfile(lockfile);
free(lockfile);
@@ -2628,7 +2630,7 @@ int cmd_receive_pack(int argc,
}
}
if (auto_update_server_info)
- update_server_info(0);
+ update_server_info(the_repository, 0);
clear_shallow_info(&si);
}
if (use_sideband)
diff --git a/builtin/refs.c b/builtin/refs.c
index a29f195834..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]")
@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
OPT_BIT(0, "dry-run", &flags,
N_("perform a non-destructive dry-run"),
REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),
+ OPT_BIT(0, "no-reflog", &flags,
+ N_("drop reflogs entirely during the migration"),
+ REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),
OPT_END(),
};
struct strbuf errbuf = STRBUF_INIT;
@@ -88,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-ext.c b/builtin/remote-ext.c
index 33c8ae0fc7..bd2037f27d 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -202,6 +202,8 @@ int cmd_remote_ext(int argc,
{
BUG_ON_NON_EMPTY_PREFIX(prefix);
+ show_usage_if_asked(argc, argv, usage_msg);
+
if (argc != 3)
usage(usage_msg);
diff --git a/builtin/remote-fd.c b/builtin/remote-fd.c
index ae896eda57..39908546ba 100644
--- a/builtin/remote-fd.c
+++ b/builtin/remote-fd.c
@@ -64,6 +64,7 @@ int cmd_remote_fd(int argc,
BUG_ON_NON_EMPTY_PREFIX(prefix);
+ show_usage_if_asked(argc, argv, usage_msg);
if (argc != 3)
usage(usage_msg);
diff --git a/builtin/remote.c b/builtin/remote.c
index 0435963286..1b7aad8838 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -383,7 +383,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
states->remote->fetch.items[i].raw);
for (ref = fetch_map; ref; ref = ref->next) {
- if (omit_name_by_refspec(ref->name, &states->remote->fetch))
+ if (refname_matches_negative_refspec_item(ref->name, &states->remote->fetch))
string_list_append(&states->skipped, abbrev_branch(ref->name));
else if (!ref->peer_ref || !refs_ref_exists(get_main_ref_store(the_repository), ref->peer_ref->name))
string_list_append(&states->new_refs, abbrev_branch(ref->name));
@@ -642,10 +642,14 @@ static int migrate_file(struct remote *remote)
strbuf_addf(&buf, "remote.%s.fetch", remote->name);
for (i = 0; i < remote->fetch.nr; i++)
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);
return 0;
@@ -820,7 +824,8 @@ static int mv(int argc, const char **argv, const char *prefix,
* Count symrefs twice, since "renaming" them is done by
* deleting and recreating them in two separate passes.
*/
- progress = start_progress(_("Renaming remote references"),
+ progress = start_progress(the_repository,
+ _("Renaming remote references"),
rename.remote_branches->nr + rename.symrefs_nr);
}
for (i = 0; i < remote_branches.nr; i++) {
diff --git a/builtin/repack.c b/builtin/repack.c
index 0c6dad7df4..75e3752353 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -41,7 +41,9 @@ static int run_update_server_info = 1;
static char *packdir, *packtmp_name, *packtmp;
static const char *const git_repack_usage[] = {
- N_("git repack [<options>]"),
+ N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
+ "[--window=<n>] [--depth=<n>] [--threads=<n>] [--keep-pack=<pack-name>]\n"
+ "[--write-midx] [--name-hash-version=<n>]"),
NULL
};
@@ -60,6 +62,7 @@ struct pack_objects_args {
int no_reuse_object;
int quiet;
int local;
+ int name_hash_version;
struct list_objects_filter_options filter_options;
};
@@ -308,6 +311,8 @@ static void prepare_pack_objects(struct child_process *cmd,
strvec_pushf(&cmd->args, "--no-reuse-delta");
if (args->no_reuse_object)
strvec_pushf(&cmd->args, "--no-reuse-object");
+ if (args->name_hash_version)
+ strvec_pushf(&cmd->args, "--name-hash-version=%d", args->name_hash_version);
if (args->local)
strvec_push(&cmd->args, "--local");
if (args->quiet)
@@ -1205,6 +1210,8 @@ int cmd_repack(int argc,
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_INTEGER(0, "name-hash-version", &po_args.name_hash_version,
+ N_("specify the name hash version to use for grouping similar objects by path")),
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")),
@@ -1370,9 +1377,12 @@ int cmd_repack(int argc,
"--unpack-unreachable");
} else if (keep_unreachable) {
strvec_push(&cmd.args, "--keep-unreachable");
- strvec_push(&cmd.args, "--pack-loose-unreachable");
}
}
+
+ if (keep_unreachable && delete_redundant &&
+ !(pack_everything & PACK_CRUFT))
+ strvec_push(&cmd.args, "--pack-loose-unreachable");
} else if (geometry.split_factor) {
strvec_push(&cmd.args, "--stdin-packs");
strvec_push(&cmd.args, "--unpacked");
@@ -1565,7 +1575,7 @@ int cmd_repack(int argc,
}
if (run_update_server_info)
- update_server_info(0);
+ update_server_info(the_repository, 0);
if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) {
unsigned flags = 0;
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/replay.c b/builtin/replay.c
index 1afc6d1ee0..032c172b65 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -163,9 +163,10 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
get_ref_information(cmd_info, &rinfo);
if (!rinfo.positive_refexprs)
die(_("need some commits to replay"));
- if (onto_name && *advance_name)
- die(_("--onto and --advance are incompatible"));
- else if (onto_name) {
+
+ die_for_incompatible_opt2(!!onto_name, "--onto",
+ !!*advance_name, "--advance");
+ if (onto_name) {
*onto = peel_committish(onto_name);
if (rinfo.positive_refexprs <
strset_get_size(&rinfo.positive_refs))
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-list.c b/builtin/rev-list.c
index 3196da7b2d..bb26bee0d4 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -22,7 +22,10 @@
#include "progress.h"
#include "reflog-walk.h"
#include "oidset.h"
+#include "oidmap.h"
#include "packfile.h"
+#include "quote.h"
+#include "strbuf.h"
static const char rev_list_usage[] =
"git rev-list [<options>] <commit>... [--] [<path>...]\n"
@@ -73,11 +76,17 @@ static unsigned progress_counter;
static struct oidset omitted_objects;
static int arg_print_omitted; /* print objects omitted by filter */
-static struct oidset missing_objects;
+struct missing_objects_map_entry {
+ struct oidmap_entry entry;
+ const char *path;
+ unsigned type;
+};
+static struct oidmap missing_objects;
enum missing_action {
MA_ERROR = 0, /* fail if any missing objects are encountered */
MA_ALLOW_ANY, /* silently allow ALL missing objects */
MA_PRINT, /* print ALL missing objects in special section */
+ MA_PRINT_INFO, /* same as MA_PRINT but also prints missing object info */
MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
};
static enum missing_action arg_missing_action;
@@ -101,7 +110,49 @@ static off_t get_object_disk_usage(struct object *obj)
return size;
}
-static inline void finish_object__ma(struct object *obj)
+static void add_missing_object_entry(struct object_id *oid, const char *path,
+ unsigned type)
+{
+ struct missing_objects_map_entry *entry;
+
+ if (oidmap_get(&missing_objects, oid))
+ return;
+
+ CALLOC_ARRAY(entry, 1);
+ entry->entry.oid = *oid;
+ entry->type = type;
+ if (path)
+ entry->path = xstrdup(path);
+ oidmap_put(&missing_objects, entry);
+}
+
+static void print_missing_object(struct missing_objects_map_entry *entry,
+ int print_missing_info)
+{
+ struct strbuf sb = STRBUF_INIT;
+
+ if (!print_missing_info) {
+ printf("?%s\n", oid_to_hex(&entry->entry.oid));
+ return;
+ }
+
+ if (entry->path && *entry->path) {
+ struct strbuf path = STRBUF_INIT;
+
+ strbuf_addstr(&sb, " path=");
+ quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
+ strbuf_addbuf(&sb, &path);
+
+ strbuf_release(&path);
+ }
+ if (entry->type)
+ strbuf_addf(&sb, " type=%s", type_name(entry->type));
+
+ printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf);
+ strbuf_release(&sb);
+}
+
+static inline void finish_object__ma(struct object *obj, const char *name)
{
/*
* Whether or not we try to dynamically fetch missing objects
@@ -119,7 +170,8 @@ static inline void finish_object__ma(struct object *obj)
return;
case MA_PRINT:
- oidset_insert(&missing_objects, &obj->oid);
+ case MA_PRINT_INFO:
+ add_missing_object_entry(&obj->oid, name, obj->type);
return;
case MA_ALLOW_PROMISOR:
@@ -152,7 +204,7 @@ static void show_commit(struct commit *commit, void *data)
if (revs->do_not_die_on_missing_objects &&
oidset_contains(&revs->missing_commits, &commit->object.oid)) {
- finish_object__ma(&commit->object);
+ finish_object__ma(&commit->object, NULL);
return;
}
@@ -268,12 +320,11 @@ static void show_commit(struct commit *commit, void *data)
finish_commit(commit);
}
-static int finish_object(struct object *obj, const char *name UNUSED,
- void *cb_data)
+static int finish_object(struct object *obj, const char *name, void *cb_data)
{
struct rev_list_info *info = cb_data;
if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
- finish_object__ma(obj);
+ finish_object__ma(obj, name);
return 1;
}
if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
@@ -414,6 +465,12 @@ static inline int parse_missing_action_value(const char *value)
return 1;
}
+ if (!strcmp(value, "print-info")) {
+ arg_missing_action = MA_PRINT_INFO;
+ fetch_if_missing = 0;
+ return 1;
+ }
+
if (!strcmp(value, "allow-promisor")) {
arg_missing_action = MA_ALLOW_PROMISOR;
fetch_if_missing = 0;
@@ -542,8 +599,7 @@ int cmd_rev_list(int argc,
const char *show_progress = NULL;
int ret = 0;
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(rev_list_usage);
+ show_usage_if_asked(argc, argv, rev_list_usage);
git_config(git_default_config, NULL);
repo_init_revisions(the_repository, &revs, prefix);
@@ -735,7 +791,8 @@ int cmd_rev_list(int argc,
revs.limited = 1;
if (show_progress)
- progress = start_delayed_progress(show_progress, 0);
+ progress = start_delayed_progress(the_repository,
+ show_progress, 0);
if (use_bitmap_index) {
if (!try_bitmap_count(&revs, filter_provided_objects))
@@ -781,10 +838,18 @@ int cmd_rev_list(int argc,
if (arg_print_omitted)
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
- if (arg_missing_action == MA_PRINT) {
- oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
+ if (arg_missing_action == MA_PRINT ||
+ arg_missing_action == MA_PRINT_INFO) {
+ struct oidset_iter iter;
+ struct object_id *oid;
+
+ oidmap_init(&missing_objects, DEFAULT_OIDSET_SIZE);
+ oidset_iter_init(&revs.missing_commits, &iter);
+
/* Add missing tips */
- oidset_insert_from_set(&missing_objects, &revs.missing_commits);
+ while ((oid = oidset_iter_next(&iter)))
+ add_missing_object_entry(oid, NULL, 0);
+
oidset_clear(&revs.missing_commits);
}
@@ -800,13 +865,20 @@ int cmd_rev_list(int argc,
printf("~%s\n", oid_to_hex(oid));
oidset_clear(&omitted_objects);
}
- if (arg_missing_action == MA_PRINT) {
- struct oidset_iter iter;
- struct object_id *oid;
- oidset_iter_init(&missing_objects, &iter);
- while ((oid = oidset_iter_next(&iter)))
- printf("?%s\n", oid_to_hex(oid));
- oidset_clear(&missing_objects);
+ if (arg_missing_action == MA_PRINT ||
+ arg_missing_action == MA_PRINT_INFO) {
+ struct missing_objects_map_entry *entry;
+ struct oidmap_iter iter;
+
+ oidmap_iter_init(&missing_objects, &iter);
+
+ while ((entry = oidmap_iter_next(&iter))) {
+ print_missing_object(entry, arg_missing_action ==
+ MA_PRINT_INFO);
+ free((void *)entry->path);
+ }
+
+ oidmap_free(&missing_objects, true);
}
stop_progress(&progress);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 949747a6b6..490da33bec 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -713,6 +713,8 @@ int cmd_rev_parse(int argc,
int seen_end_of_options = 0;
enum format_type format = FORMAT_DEFAULT;
+ show_usage_if_asked(argc, argv, builtin_rev_parse_usage);
+
if (argc > 1 && !strcmp("--parseopt", argv[1]))
return cmd_parseopt(argc - 1, argv + 1, prefix);
@@ -787,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++;
@@ -1081,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 59b626aae8..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(&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/show-index.c b/builtin/show-index.c
index 756d632b51..9d4ecf5e7b 100644
--- a/builtin/show-index.c
+++ b/builtin/show-index.c
@@ -9,7 +9,7 @@
#include "parse-options.h"
static const char *const show_index_usage[] = {
- "git show-index [--object-format=<hash-algorithm>]",
+ "git show-index [--object-format=<hash-algorithm>] < <pack-idx-file>",
NULL
};
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 c4bd145831..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);
}
@@ -698,7 +698,6 @@ int cmd_tag(int argc,
cleanup:
ref_sorting_release(sorting);
ref_filter_clear(&filter);
- ref_format_clear(&format);
strbuf_release(&buf);
strbuf_release(&ref);
strbuf_release(&reflog_msg);
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index 6da2825753..fb5fcbc40a 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -26,6 +26,9 @@ static char *create_temp_file(struct object_id *oid)
return path;
}
+static const char usage_msg[] =
+"git unpack-file <blob>";
+
int cmd_unpack_file(int argc,
const char **argv,
const char *prefix UNUSED,
@@ -33,8 +36,9 @@ int cmd_unpack_file(int argc,
{
struct object_id oid;
- if (argc != 2 || !strcmp(argv[1], "-h"))
- usage("git unpack-file <blob>");
+ show_usage_if_asked(argc, argv, usage_msg);
+ if (argc != 2)
+ usage(usage_msg);
if (repo_get_oid(the_repository, argv[1], &oid))
die("Not a valid object name %s", argv[1]);
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 2197d6d933..8383bcf404 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -18,6 +18,7 @@
#include "progress.h"
#include "decorate.h"
#include "fsck.h"
+#include "packfile.h"
static int dry_run, quiet, recover, has_errors, strict;
static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]";
@@ -27,7 +28,7 @@ static unsigned char buffer[4096];
static unsigned int offset, len;
static off_t consumed_bytes;
static off_t max_input_size;
-static git_hash_ctx ctx;
+static struct git_hash_ctx ctx;
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
static struct progress *progress;
@@ -69,7 +70,7 @@ static void *fill(int min)
if (min > sizeof(buffer))
die("cannot fill %d bytes", min);
if (offset) {
- the_hash_algo->update_fn(&ctx, buffer, offset);
+ git_hash_update(&ctx, buffer, offset);
memmove(buffer, buffer + offset, len);
offset = 0;
}
@@ -578,19 +579,21 @@ static void unpack_one(unsigned nr)
static void unpack_all(void)
{
int i;
- struct pack_header *hdr = fill(sizeof(struct pack_header));
+ unsigned char *hdr = fill(sizeof(struct pack_header));
- nr_objects = ntohl(hdr->hdr_entries);
-
- if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
+ if (get_be32(hdr) != PACK_SIGNATURE)
die("bad pack file");
- if (!pack_version_ok(hdr->hdr_version))
+ hdr += 4;
+ if (!pack_version_ok_native(get_be32(hdr)))
die("unknown pack file version %"PRIu32,
- ntohl(hdr->hdr_version));
+ get_be32(hdr));
+ hdr += 4;
+ nr_objects = get_be32(hdr);
use(sizeof(struct pack_header));
if (!quiet)
- progress = start_progress(_("Unpacking objects"), nr_objects);
+ progress = start_progress(the_repository,
+ _("Unpacking objects"), nr_objects);
CALLOC_ARRAY(obj_list, nr_objects);
begin_odb_transaction();
for (i = 0; i < nr_objects; i++) {
@@ -611,7 +614,7 @@ int cmd_unpack_objects(int argc,
{
int i;
struct object_id oid;
- git_hash_ctx tmp_ctx;
+ struct git_hash_ctx tmp_ctx;
disable_replace_refs();
@@ -619,6 +622,8 @@ int cmd_unpack_objects(int argc,
quiet = !isatty(2);
+ show_usage_if_asked(argc, argv, unpack_usage);
+
for (i = 1 ; i < argc; i++) {
const char *arg = argv[i];
@@ -644,19 +649,10 @@ int cmd_unpack_objects(int argc,
fsck_set_msg_types(&fsck_options, arg);
continue;
}
- if (starts_with(arg, "--pack_header=")) {
- struct pack_header *hdr;
- char *c;
-
- hdr = (struct pack_header *)buffer;
- hdr->hdr_signature = htonl(PACK_SIGNATURE);
- hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
- if (*c != ',')
- die("bad %s", arg);
- hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
- if (*c)
- die("bad %s", arg);
- len = sizeof(*hdr);
+ if (skip_prefix(arg, "--pack_header=", &arg)) {
+ if (parse_pack_header_option(arg,
+ buffer, &len) < 0)
+ die(_("bad --pack_header: %s"), arg);
continue;
}
if (skip_prefix(arg, "--max-input-size=", &arg)) {
@@ -671,10 +667,9 @@ int cmd_unpack_objects(int argc,
}
the_hash_algo->init_fn(&ctx);
unpack_all();
- the_hash_algo->update_fn(&ctx, buffer, offset);
- the_hash_algo->init_fn(&tmp_ctx);
- the_hash_algo->clone_fn(&tmp_ctx, &ctx);
- the_hash_algo->final_oid_fn(&oid, &tmp_ctx);
+ git_hash_update(&ctx, buffer, offset);
+ git_hash_clone(&tmp_ctx, &ctx);
+ git_hash_final_oid(&oid, &tmp_ctx);
if (strict) {
write_rest();
if (fsck_finish(&fsck_options))
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 74bbad9f87..b2f6b1a3fb 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -1045,8 +1045,8 @@ int cmd_update_index(int argc,
OPT_END()
};
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(update_index_usage, options);
+ show_usage_with_options_if_asked(argc, argv,
+ update_index_usage, options);
git_config(git_default_config, NULL);
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/update-server-info.c b/builtin/update-server-info.c
index 6769611a02..d7467290a8 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -13,7 +12,7 @@ static const char * const update_server_info_usage[] = {
int cmd_update_server_info(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int force = 0;
struct option options[] = {
@@ -21,11 +20,12 @@ int cmd_update_server_info(int argc,
OPT_END()
};
- git_config(git_default_config, NULL);
+ if (repo)
+ repo_config(repo, git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options,
update_server_info_usage, 0);
if (argc > 0)
usage_with_options(update_server_info_usage, options);
- return !!update_server_info(force);
+ return !!update_server_info(repo, force);
}
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 9e9343f121..97d7c9522f 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -27,7 +27,8 @@ int cmd_upload_archive_writer(int argc,
const char *arg_cmd = "argument ";
int ret;
- if (argc != 2 || !strcmp(argv[1], "-h"))
+ show_usage_if_asked(argc, argv, upload_archive_usage);
+ if (argc != 2)
usage(upload_archive_usage);
if (!enter_repo(argv[1], 0))
@@ -92,8 +93,7 @@ struct repository *repo UNUSED)
BUG_ON_NON_EMPTY_PREFIX(prefix);
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage(upload_archive_usage);
+ show_usage_if_asked(argc, argv, upload_archive_usage);
/*
* Set up sideband subprocess.
diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
index dd63d6eadf..c2bbc035ab 100644
--- a/builtin/upload-pack.c
+++ b/builtin/upload-pack.c
@@ -1,3 +1,5 @@
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "builtin.h"
#include "exec-cmd.h"
#include "gettext.h"
@@ -63,9 +65,9 @@ int cmd_upload_pack(int argc,
switch (determine_protocol_version_server()) {
case protocol_v2:
if (advertise_refs)
- protocol_v2_advertise_capabilities();
+ protocol_v2_advertise_capabilities(the_repository);
else
- protocol_v2_serve_loop(stateless_rpc);
+ protocol_v2_serve_loop(the_repository, stateless_rpc);
break;
case protocol_v1:
/*
diff --git a/builtin/var.c b/builtin/var.c
index 1449656cc9..ada642a9fe 100644
--- a/builtin/var.c
+++ b/builtin/var.c
@@ -42,7 +42,7 @@ static char *sequence_editor(int ident_flag UNUSED)
static char *pager(int ident_flag UNUSED)
{
- const char *pgm = git_pager(1);
+ const char *pgm = git_pager(the_repository, 1);
if (!pgm)
pgm = "cat";
@@ -221,6 +221,7 @@ int cmd_var(int argc,
const struct git_var *git_var;
char *val;
+ show_usage_if_asked(argc, argv, var_usage);
if (argc != 2)
usage(var_usage);
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 a7f20618ff..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;
}
@@ -69,6 +68,5 @@ int cmd_verify_tag(int argc,
if (format.format)
pretty_print_ref(name, &oid, &format);
}
- ref_format_clear(&format);
return had_error;
}
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"));