aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/archive.c7
-rw-r--r--builtin/bisect.c4
-rw-r--r--builtin/bundle.c2
-rw-r--r--builtin/cat-file.c3
-rw-r--r--builtin/check-mailmap.c25
-rw-r--r--builtin/config.c2
-rw-r--r--builtin/diff-index.c4
-rw-r--r--builtin/fetch-pack.c20
-rw-r--r--builtin/fetch.c28
-rw-r--r--builtin/gc.c393
-rw-r--r--builtin/index-pack.c9
-rw-r--r--builtin/interpret-trailers.c1
-rw-r--r--builtin/merge-tree.c13
-rw-r--r--builtin/pack-objects.c54
-rw-r--r--builtin/remote.c23
-rw-r--r--builtin/repack.c36
-rw-r--r--builtin/send-pack.c1
-rw-r--r--builtin/sparse-checkout.c21
-rw-r--r--builtin/stash.c2
-rw-r--r--builtin/submodule--helper.c2
-rw-r--r--builtin/update-ref.c8
-rw-r--r--builtin/upload-archive.c8
22 files changed, 441 insertions, 225 deletions
diff --git a/builtin/archive.c b/builtin/archive.c
index b50981504f..63f02990d1 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -100,13 +100,16 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
if (output)
create_output_file(output);
- if (remote)
- return run_remote_archiver(argc, argv, remote, exec, output);
+ if (remote) {
+ ret = run_remote_archiver(argc, argv, remote, exec, output);
+ goto out;
+ }
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
ret = write_archive(argc, argv, prefix, the_repository, output, 0);
+out:
free(output);
return ret;
}
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 453a6cccd7..c8aa92b19d 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -583,7 +583,7 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
add_bisect_ref, good, "refs/bisect/", &cb);
if (prepare_revision_walk(revs))
- res = error(_("revision walk setup failed\n"));
+ res = error(_("revision walk setup failed"));
free(good);
free(bad);
@@ -1108,7 +1108,7 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, int argc,
setup_revisions(2, argv + i - 1, &revs, NULL);
if (prepare_revision_walk(&revs))
- die(_("revision walk setup failed\n"));
+ die(_("revision walk setup failed"));
while ((commit = get_revision(&revs)) != NULL)
strvec_push(&argv_state,
oid_to_hex(&commit->object.oid));
diff --git a/builtin/bundle.c b/builtin/bundle.c
index 86d0ed7049..b858552ee6 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -221,7 +221,9 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
&extra_index_pack_args, 0) ||
list_bundle_refs(&header, argc, argv);
bundle_header_release(&header);
+
cleanup:
+ strvec_clear(&extra_index_pack_args);
free(bundle_file);
return ret;
}
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 18fe58d6b8..1afdfb5cba 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -1047,6 +1047,9 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
if (batch.buffer_output < 0)
batch.buffer_output = batch.all_objects;
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
/* Return early if we're in batch mode? */
if (batch.enabled) {
if (opt_cw)
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index b8a05b8e07..2334b57222 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -9,6 +9,7 @@
#include "write-or-die.h"
static int use_stdin;
+static const char *mailmap_file, *mailmap_blob;
static const char * const check_mailmap_usage[] = {
N_("git check-mailmap [<options>] <contact>..."),
NULL
@@ -16,6 +17,8 @@ NULL
static const struct option check_mailmap_options[] = {
OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")),
+ OPT_FILENAME(0, "mailmap-file", &mailmap_file, N_("read additional mailmap entries from file")),
+ OPT_STRING(0, "mailmap-blob", &mailmap_blob, N_("blob"), N_("read additional mailmap entries from blob")),
OPT_END()
};
@@ -25,13 +28,17 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
size_t namelen, maillen;
struct ident_split ident;
- if (split_ident_line(&ident, contact, strlen(contact)))
- die(_("unable to parse contact: %s"), contact);
-
- name = ident.name_begin;
- namelen = ident.name_end - ident.name_begin;
- mail = ident.mail_begin;
- maillen = ident.mail_end - ident.mail_begin;
+ if (!split_ident_line(&ident, contact, strlen(contact))) {
+ name = ident.name_begin;
+ namelen = ident.name_end - ident.name_begin;
+ mail = ident.mail_begin;
+ maillen = ident.mail_end - ident.mail_begin;
+ } else {
+ name = NULL;
+ namelen = 0;
+ mail = contact;
+ maillen = strlen(contact);
+ }
map_user(mailmap, &mail, &maillen, &name, &namelen);
@@ -52,6 +59,10 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
die(_("no contacts specified"));
read_mailmap(&mailmap);
+ if (mailmap_blob)
+ read_mailmap_blob(&mailmap, mailmap_blob);
+ if (mailmap_file)
+ read_mailmap_file(&mailmap, mailmap_file, 0);
for (i = 0; i < argc; ++i)
check_mailmap(&mailmap, argv[i]);
diff --git a/builtin/config.c b/builtin/config.c
index e00d983596..95c8a00915 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -17,7 +17,7 @@
static const char *const builtin_config_usage[] = {
N_("git config list [<file-option>] [<display-option>] [--includes]"),
- N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
+ N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config rename-section [<file-option>] <old-name> <new-name>"),
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 3e05260ac0..685b60284f 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -25,6 +25,10 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
usage(diff_cache_usage);
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
repo_init_revisions(the_repository, &rev, prefix);
rev.abbrev = 0;
prefix = precompose_argv_prefix(argc, argv, prefix);
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index af329e8d5c..fe404d1305 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -46,7 +46,7 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
{
int i, ret;
- struct ref *ref = NULL;
+ struct ref *fetched_refs = NULL, *remote_refs = NULL;
const char *dest = NULL;
struct ref **sought = NULL;
int nr_sought = 0, alloc_sought = 0;
@@ -228,19 +228,20 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
version = discover_version(&reader);
switch (version) {
case protocol_v2:
- get_remote_refs(fd[1], &reader, &ref, 0, NULL, NULL,
+ get_remote_refs(fd[1], &reader, &remote_refs, 0, NULL, NULL,
args.stateless_rpc);
break;
case protocol_v1:
case protocol_v0:
- get_remote_heads(&reader, &ref, 0, NULL, &shallow);
+ get_remote_heads(&reader, &remote_refs, 0, NULL, &shallow);
break;
case protocol_unknown_version:
BUG("unknown protocol version");
}
- ref = fetch_pack(&args, fd, ref, sought, nr_sought,
+ fetched_refs = fetch_pack(&args, fd, remote_refs, sought, nr_sought,
&shallow, pack_lockfiles_ptr, version);
+
if (pack_lockfiles.nr) {
int i;
@@ -260,7 +261,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
if (finish_connect(conn))
return 1;
- ret = !ref;
+ ret = !fetched_refs;
/*
* If the heads to pull were given, we should have consumed
@@ -270,11 +271,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix UNUSED)
*/
ret |= report_unmatched_refs(sought, nr_sought);
- while (ref) {
+ for (struct ref *ref = fetched_refs; ref; ref = ref->next)
printf("%s %s\n",
oid_to_hex(&ref->old_oid), ref->name);
- ref = ref->next;
- }
+ for (size_t i = 0; i < nr_sought; i++)
+ free_one_ref(sought[i]);
+ free(sought);
+ free_refs(fetched_refs);
+ free_refs(remote_refs);
return ret;
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c297569a47..55f97134aa 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1161,7 +1161,7 @@ static int store_updated_refs(struct display_state *display_state,
opt.exclude_hidden_refs_section = "fetch";
rm = ref_map;
if (check_connected(iterate_ref_map, &rm, &opt)) {
- rc = error(_("%s did not send all necessary objects\n"),
+ rc = error(_("%s did not send all necessary objects"),
display_state->url);
goto abort;
}
@@ -1458,7 +1458,7 @@ static void set_option(struct transport *transport, const char *name, const char
die(_("option \"%s\" value \"%s\" is not valid for %s"),
name, value, transport->url);
if (r > 0)
- warning(_("option \"%s\" is ignored for %s\n"),
+ warning(_("option \"%s\" is ignored for %s"),
name, transport->url);
}
@@ -1731,11 +1731,8 @@ static int do_fetch(struct transport *transport,
goto cleanup;
retcode = ref_transaction_commit(transaction, &err);
- if (retcode) {
- ref_transaction_free(transaction);
- transaction = NULL;
+ if (retcode)
goto cleanup;
- }
}
commit_fetch_head(&fetch_head);
@@ -1803,8 +1800,11 @@ cleanup:
if (transaction && ref_transaction_abort(transaction, &err) &&
err.len)
error("%s", err.buf);
+ transaction = NULL;
}
+ if (transaction)
+ ref_transaction_free(transaction);
display_state_release(&display_state);
close_fetch_head(&fetch_head);
strbuf_release(&err);
@@ -2408,6 +2408,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
struct oidset_iter iter;
const struct object_id *oid;
+ trace2_region_enter("fetch", "negotiate-only", the_repository);
if (!remote)
die(_("must supply remote when using --negotiate-only"));
gtransport = prepare_transport(remote, 1);
@@ -2416,6 +2417,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
} else {
warning(_("protocol does not support --negotiate-only, exiting"));
result = 1;
+ trace2_region_leave("fetch", "negotiate-only", the_repository);
goto cleanup;
}
if (server_options.nr)
@@ -2426,11 +2428,17 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
while ((oid = oidset_iter_next(&iter)))
printf("%s\n", oid_to_hex(oid));
oidset_clear(&acked_commits);
+ trace2_region_leave("fetch", "negotiate-only", the_repository);
} else if (remote) {
- if (filter_options.choice || repo_has_promisor_remote(the_repository))
+ if (filter_options.choice || repo_has_promisor_remote(the_repository)) {
+ trace2_region_enter("fetch", "setup-partial", the_repository);
fetch_one_setup_partial(remote);
+ trace2_region_leave("fetch", "setup-partial", the_repository);
+ }
+ trace2_region_enter("fetch", "fetch-one", the_repository);
result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs,
&config);
+ trace2_region_leave("fetch", "fetch-one", the_repository);
} else {
int max_children = max_jobs;
@@ -2450,7 +2458,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
max_children = config.parallel;
/* TODO should this also die if we have a previous partial-clone? */
+ trace2_region_enter("fetch", "fetch-multiple", the_repository);
result = fetch_multiple(&list, max_children, &config);
+ trace2_region_leave("fetch", "fetch-multiple", the_repository);
}
/*
@@ -2472,6 +2482,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
max_children = config.parallel;
add_options_to_argv(&options, &config);
+ trace2_region_enter_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix);
result = fetch_submodules(the_repository,
&options,
submodule_prefix,
@@ -2479,6 +2490,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
recurse_submodules_default,
verbosity < 0,
max_children);
+ trace2_region_leave_printf("fetch", "recurse-submodule", the_repository, "%s", submodule_prefix);
strvec_clear(&options);
}
@@ -2502,9 +2514,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (progress)
commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS;
+ trace2_region_enter("fetch", "write-commit-graph", the_repository);
write_commit_graph_reachable(the_repository->objects->odb,
commit_graph_flags,
NULL);
+ trace2_region_leave("fetch", "write-commit-graph", the_repository);
}
if (enable_auto_gc) {
diff --git a/builtin/gc.c b/builtin/gc.c
index 45f14fb09b..7dac971405 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -49,23 +49,7 @@ static const char * const builtin_gc_usage[] = {
NULL
};
-static int pack_refs = 1;
-static int prune_reflogs = 1;
-static int cruft_packs = 1;
-static unsigned long max_cruft_size;
-static int aggressive_depth = 50;
-static int aggressive_window = 250;
-static int gc_auto_threshold = 6700;
-static int gc_auto_pack_limit = 50;
-static int detach_auto = 1;
static timestamp_t gc_log_expire_time;
-static const char *gc_log_expire = "1.day.ago";
-static const char *prune_expire = "2.weeks.ago";
-static const char *prune_worktrees_expire = "3.months.ago";
-static char *repack_filter;
-static char *repack_filter_to;
-static unsigned long big_pack_threshold;
-static unsigned long max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE;
static struct strvec reflog = STRVEC_INIT;
static struct strvec repack = STRVEC_INIT;
@@ -125,13 +109,6 @@ static void process_log_file_at_exit(void)
process_log_file();
}
-static void process_log_file_on_signal(int signo)
-{
- process_log_file();
- sigchain_pop(signo);
- raise(signo);
-}
-
static int gc_config_is_timestamp_never(const char *var)
{
const char *value;
@@ -145,37 +122,100 @@ static int gc_config_is_timestamp_never(const char *var)
return 0;
}
-static void gc_config(void)
+struct gc_config {
+ int pack_refs;
+ int prune_reflogs;
+ int cruft_packs;
+ unsigned long max_cruft_size;
+ int aggressive_depth;
+ int aggressive_window;
+ int gc_auto_threshold;
+ int gc_auto_pack_limit;
+ int detach_auto;
+ char *gc_log_expire;
+ char *prune_expire;
+ char *prune_worktrees_expire;
+ char *repack_filter;
+ char *repack_filter_to;
+ unsigned long big_pack_threshold;
+ unsigned long max_delta_cache_size;
+};
+
+#define GC_CONFIG_INIT { \
+ .pack_refs = 1, \
+ .prune_reflogs = 1, \
+ .cruft_packs = 1, \
+ .aggressive_depth = 50, \
+ .aggressive_window = 250, \
+ .gc_auto_threshold = 6700, \
+ .gc_auto_pack_limit = 50, \
+ .detach_auto = 1, \
+ .gc_log_expire = xstrdup("1.day.ago"), \
+ .prune_expire = xstrdup("2.weeks.ago"), \
+ .prune_worktrees_expire = xstrdup("3.months.ago"), \
+ .max_delta_cache_size = DEFAULT_DELTA_CACHE_SIZE, \
+}
+
+static void gc_config_release(struct gc_config *cfg)
+{
+ free(cfg->gc_log_expire);
+ free(cfg->prune_expire);
+ free(cfg->prune_worktrees_expire);
+ free(cfg->repack_filter);
+ free(cfg->repack_filter_to);
+}
+
+static void gc_config(struct gc_config *cfg)
{
const char *value;
+ char *owned = NULL;
if (!git_config_get_value("gc.packrefs", &value)) {
if (value && !strcmp(value, "notbare"))
- pack_refs = -1;
+ cfg->pack_refs = -1;
else
- pack_refs = git_config_bool("gc.packrefs", value);
+ cfg->pack_refs = git_config_bool("gc.packrefs", value);
}
if (gc_config_is_timestamp_never("gc.reflogexpire") &&
gc_config_is_timestamp_never("gc.reflogexpireunreachable"))
- prune_reflogs = 0;
+ cfg->prune_reflogs = 0;
+
+ git_config_get_int("gc.aggressivewindow", &cfg->aggressive_window);
+ git_config_get_int("gc.aggressivedepth", &cfg->aggressive_depth);
+ git_config_get_int("gc.auto", &cfg->gc_auto_threshold);
+ git_config_get_int("gc.autopacklimit", &cfg->gc_auto_pack_limit);
+ git_config_get_bool("gc.autodetach", &cfg->detach_auto);
+ git_config_get_bool("gc.cruftpacks", &cfg->cruft_packs);
+ git_config_get_ulong("gc.maxcruftsize", &cfg->max_cruft_size);
+
+ if (!repo_config_get_expiry(the_repository, "gc.pruneexpire", &owned)) {
+ free(cfg->prune_expire);
+ cfg->prune_expire = owned;
+ }
- git_config_get_int("gc.aggressivewindow", &aggressive_window);
- git_config_get_int("gc.aggressivedepth", &aggressive_depth);
- git_config_get_int("gc.auto", &gc_auto_threshold);
- git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
- git_config_get_bool("gc.autodetach", &detach_auto);
- git_config_get_bool("gc.cruftpacks", &cruft_packs);
- git_config_get_ulong("gc.maxcruftsize", &max_cruft_size);
- repo_config_get_expiry(the_repository, "gc.pruneexpire", &prune_expire);
- repo_config_get_expiry(the_repository, "gc.worktreepruneexpire", &prune_worktrees_expire);
- repo_config_get_expiry(the_repository, "gc.logexpiry", &gc_log_expire);
+ if (!repo_config_get_expiry(the_repository, "gc.worktreepruneexpire", &owned)) {
+ free(cfg->prune_worktrees_expire);
+ cfg->prune_worktrees_expire = owned;
+ }
- git_config_get_ulong("gc.bigpackthreshold", &big_pack_threshold);
- git_config_get_ulong("pack.deltacachesize", &max_delta_cache_size);
+ if (!repo_config_get_expiry(the_repository, "gc.logexpiry", &owned)) {
+ free(cfg->gc_log_expire);
+ cfg->gc_log_expire = owned;
+ }
+
+ git_config_get_ulong("gc.bigpackthreshold", &cfg->big_pack_threshold);
+ git_config_get_ulong("pack.deltacachesize", &cfg->max_delta_cache_size);
+
+ if (!git_config_get_string("gc.repackfilter", &owned)) {
+ free(cfg->repack_filter);
+ cfg->repack_filter = owned;
+ }
- git_config_get_string("gc.repackfilter", &repack_filter);
- git_config_get_string("gc.repackfilterto", &repack_filter_to);
+ if (!git_config_get_string("gc.repackfilterto", &owned)) {
+ free(cfg->repack_filter_to);
+ cfg->repack_filter_to = owned;
+ }
git_config(git_default_config, NULL);
}
@@ -202,11 +242,15 @@ static enum schedule_priority parse_schedule(const char *value)
struct maintenance_run_opts {
int auto_flag;
+ int detach;
int quiet;
enum schedule_priority schedule;
};
+#define MAINTENANCE_RUN_OPTS_INIT { \
+ .detach = -1, \
+}
-static int pack_refs_condition(void)
+static int pack_refs_condition(UNUSED struct gc_config *cfg)
{
/*
* The auto-repacking logic for refs is handled by the ref backends and
@@ -216,7 +260,8 @@ static int pack_refs_condition(void)
return 1;
}
-static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts)
+static int maintenance_task_pack_refs(struct maintenance_run_opts *opts,
+ UNUSED struct gc_config *cfg)
{
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -228,7 +273,7 @@ static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *
return run_command(&cmd);
}
-static int too_many_loose_objects(void)
+static int too_many_loose_objects(struct gc_config *cfg)
{
/*
* Quickly check if a "gc" is needed, by estimating how
@@ -247,7 +292,7 @@ static int too_many_loose_objects(void)
if (!dir)
return 0;
- auto_threshold = DIV_ROUND_UP(gc_auto_threshold, 256);
+ auto_threshold = DIV_ROUND_UP(cfg->gc_auto_threshold, 256);
while ((ent = readdir(dir)) != NULL) {
if (strspn(ent->d_name, "0123456789abcdef") != hexsz_loose ||
ent->d_name[hexsz_loose] != '\0')
@@ -283,12 +328,12 @@ static struct packed_git *find_base_packs(struct string_list *packs,
return base;
}
-static int too_many_packs(void)
+static int too_many_packs(struct gc_config *cfg)
{
struct packed_git *p;
int cnt;
- if (gc_auto_pack_limit <= 0)
+ if (cfg->gc_auto_pack_limit <= 0)
return 0;
for (cnt = 0, p = get_all_packs(the_repository); p; p = p->next) {
@@ -302,7 +347,7 @@ static int too_many_packs(void)
*/
cnt++;
}
- return gc_auto_pack_limit < cnt;
+ return cfg->gc_auto_pack_limit < cnt;
}
static uint64_t total_ram(void)
@@ -336,7 +381,8 @@ static uint64_t total_ram(void)
return 0;
}
-static uint64_t estimate_repack_memory(struct packed_git *pack)
+static uint64_t estimate_repack_memory(struct gc_config *cfg,
+ struct packed_git *pack)
{
unsigned long nr_objects = repo_approximate_object_count(the_repository);
size_t os_cache, heap;
@@ -373,7 +419,7 @@ static uint64_t estimate_repack_memory(struct packed_git *pack)
*/
heap += delta_base_cache_limit;
/* and of course pack-objects has its own delta cache */
- heap += max_delta_cache_size;
+ heap += cfg->max_delta_cache_size;
return os_cache + heap;
}
@@ -384,30 +430,31 @@ static int keep_one_pack(struct string_list_item *item, void *data UNUSED)
return 0;
}
-static void add_repack_all_option(struct string_list *keep_pack)
+static void add_repack_all_option(struct gc_config *cfg,
+ struct string_list *keep_pack)
{
- if (prune_expire && !strcmp(prune_expire, "now"))
+ if (cfg->prune_expire && !strcmp(cfg->prune_expire, "now"))
strvec_push(&repack, "-a");
- else if (cruft_packs) {
+ else if (cfg->cruft_packs) {
strvec_push(&repack, "--cruft");
- if (prune_expire)
- strvec_pushf(&repack, "--cruft-expiration=%s", prune_expire);
- if (max_cruft_size)
+ if (cfg->prune_expire)
+ strvec_pushf(&repack, "--cruft-expiration=%s", cfg->prune_expire);
+ if (cfg->max_cruft_size)
strvec_pushf(&repack, "--max-cruft-size=%lu",
- max_cruft_size);
+ cfg->max_cruft_size);
} else {
strvec_push(&repack, "-A");
- if (prune_expire)
- strvec_pushf(&repack, "--unpack-unreachable=%s", prune_expire);
+ if (cfg->prune_expire)
+ strvec_pushf(&repack, "--unpack-unreachable=%s", cfg->prune_expire);
}
if (keep_pack)
for_each_string_list(keep_pack, keep_one_pack, NULL);
- if (repack_filter && *repack_filter)
- strvec_pushf(&repack, "--filter=%s", repack_filter);
- if (repack_filter_to && *repack_filter_to)
- strvec_pushf(&repack, "--filter-to=%s", repack_filter_to);
+ if (cfg->repack_filter && *cfg->repack_filter)
+ strvec_pushf(&repack, "--filter=%s", cfg->repack_filter);
+ if (cfg->repack_filter_to && *cfg->repack_filter_to)
+ strvec_pushf(&repack, "--filter-to=%s", cfg->repack_filter_to);
}
static void add_repack_incremental_option(void)
@@ -415,13 +462,13 @@ static void add_repack_incremental_option(void)
strvec_push(&repack, "--no-write-bitmap-index");
}
-static int need_to_gc(void)
+static int need_to_gc(struct gc_config *cfg)
{
/*
* Setting gc.auto to 0 or negative can disable the
* automatic gc.
*/
- if (gc_auto_threshold <= 0)
+ if (cfg->gc_auto_threshold <= 0)
return 0;
/*
@@ -430,13 +477,13 @@ static int need_to_gc(void)
* we run "repack -A -d -l". Otherwise we tell the caller
* there is no need.
*/
- if (too_many_packs()) {
+ if (too_many_packs(cfg)) {
struct string_list keep_pack = STRING_LIST_INIT_NODUP;
- if (big_pack_threshold) {
- find_base_packs(&keep_pack, big_pack_threshold);
- if (keep_pack.nr >= gc_auto_pack_limit) {
- big_pack_threshold = 0;
+ if (cfg->big_pack_threshold) {
+ find_base_packs(&keep_pack, cfg->big_pack_threshold);
+ if (keep_pack.nr >= cfg->gc_auto_pack_limit) {
+ cfg->big_pack_threshold = 0;
string_list_clear(&keep_pack, 0);
find_base_packs(&keep_pack, 0);
}
@@ -445,7 +492,7 @@ static int need_to_gc(void)
uint64_t mem_have, mem_want;
mem_have = total_ram();
- mem_want = estimate_repack_memory(p);
+ mem_want = estimate_repack_memory(cfg, p);
/*
* Only allow 1/2 of memory for pack-objects, leave
@@ -456,9 +503,9 @@ static int need_to_gc(void)
string_list_clear(&keep_pack, 0);
}
- add_repack_all_option(&keep_pack);
+ add_repack_all_option(cfg, &keep_pack);
string_list_clear(&keep_pack, 0);
- } else if (too_many_loose_objects())
+ } else if (too_many_loose_objects(cfg))
add_repack_incremental_option();
else
return 0;
@@ -585,7 +632,8 @@ done:
return ret;
}
-static void gc_before_repack(struct maintenance_run_opts *opts)
+static void gc_before_repack(struct maintenance_run_opts *opts,
+ struct gc_config *cfg)
{
/*
* We may be called twice, as both the pre- and
@@ -596,10 +644,10 @@ static void gc_before_repack(struct maintenance_run_opts *opts)
if (done++)
return;
- if (pack_refs && maintenance_task_pack_refs(opts))
+ if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg))
die(FAILED_RUN, "pack-refs");
- if (prune_reflogs) {
+ if (cfg->prune_reflogs) {
struct child_process cmd = CHILD_PROCESS_INIT;
cmd.git_cmd = 1;
@@ -620,19 +668,25 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
int keep_largest_pack = -1;
timestamp_t dummy;
struct child_process rerere_cmd = CHILD_PROCESS_INIT;
- struct maintenance_run_opts opts = {0};
+ struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
+ struct gc_config cfg = GC_CONFIG_INIT;
+ 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, N_("date"),
+ { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"),
N_("prune unreferenced objects"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
- OPT_BOOL(0, "cruft", &cruft_packs, N_("pack unreferenced objects separately")),
- OPT_MAGNITUDE(0, "max-cruft-size", &max_cruft_size,
+ PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg },
+ OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")),
+ OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size,
N_("with --cruft, limit the size of new cruft packs")),
OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"),
PARSE_OPT_NOCOMPLETE),
+ OPT_BOOL(0, "detach", &opts.detach,
+ N_("perform garbage collection in the background")),
OPT_BOOL_F(0, "force", &force,
N_("force running gc even if there may be another gc running"),
PARSE_OPT_NOCOMPLETE),
@@ -650,84 +704,103 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
strvec_pushl(&rerere, "rerere", "gc", NULL);
- /* default expiry time, overwritten in gc_config */
- gc_config();
- if (parse_expiry_date(gc_log_expire, &gc_log_expire_time))
- die(_("failed to parse gc.logExpiry value %s"), gc_log_expire);
+ gc_config(&cfg);
- if (pack_refs < 0)
- pack_refs = !is_bare_repository();
+ if (parse_expiry_date(cfg.gc_log_expire, &gc_log_expire_time))
+ die(_("failed to parse gc.logExpiry value %s"), cfg.gc_log_expire);
+
+ if (cfg.pack_refs < 0)
+ cfg.pack_refs = !is_bare_repository();
argc = parse_options(argc, argv, prefix, builtin_gc_options,
builtin_gc_usage, 0);
if (argc > 0)
usage_with_options(builtin_gc_usage, builtin_gc_options);
- if (prune_expire && parse_expiry_date(prune_expire, &dummy))
- die(_("failed to parse prune expiry value %s"), prune_expire);
+ if (prune_expire_arg != prune_expire_sentinel) {
+ free(cfg.prune_expire);
+ cfg.prune_expire = xstrdup_or_null(prune_expire_arg);
+ }
+ if (cfg.prune_expire && parse_expiry_date(cfg.prune_expire, &dummy))
+ die(_("failed to parse prune expiry value %s"), cfg.prune_expire);
if (aggressive) {
strvec_push(&repack, "-f");
- if (aggressive_depth > 0)
- strvec_pushf(&repack, "--depth=%d", aggressive_depth);
- if (aggressive_window > 0)
- strvec_pushf(&repack, "--window=%d", aggressive_window);
+ if (cfg.aggressive_depth > 0)
+ strvec_pushf(&repack, "--depth=%d", cfg.aggressive_depth);
+ if (cfg.aggressive_window > 0)
+ strvec_pushf(&repack, "--window=%d", cfg.aggressive_window);
}
if (quiet)
strvec_push(&repack, "-q");
if (opts.auto_flag) {
+ if (cfg.detach_auto && opts.detach < 0)
+ opts.detach = 1;
+
/*
* Auto-gc should be least intrusive as possible.
*/
- if (!need_to_gc())
- return 0;
+ if (!need_to_gc(&cfg)) {
+ ret = 0;
+ goto out;
+ }
+
if (!quiet) {
- if (detach_auto)
+ if (opts.detach > 0)
fprintf(stderr, _("Auto packing the repository in background for optimum performance.\n"));
else
fprintf(stderr, _("Auto packing the repository for optimum performance.\n"));
fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
}
- if (detach_auto) {
- int ret = report_last_gc_error();
-
- if (ret == 1)
- /* Last gc --auto failed. Skip this one. */
- return 0;
- else if (ret)
- /* an I/O error occurred, already reported */
- return ret;
-
- if (lock_repo_for_gc(force, &pid))
- return 0;
- gc_before_repack(&opts); /* dies on failure */
- delete_tempfile(&pidfile);
-
- /*
- * failure to daemonize is ok, we'll continue
- * in foreground
- */
- daemonized = !daemonize();
- }
} else {
struct string_list keep_pack = STRING_LIST_INIT_NODUP;
if (keep_largest_pack != -1) {
if (keep_largest_pack)
find_base_packs(&keep_pack, 0);
- } else if (big_pack_threshold) {
- find_base_packs(&keep_pack, big_pack_threshold);
+ } else if (cfg.big_pack_threshold) {
+ find_base_packs(&keep_pack, cfg.big_pack_threshold);
}
- add_repack_all_option(&keep_pack);
+ add_repack_all_option(&cfg, &keep_pack);
string_list_clear(&keep_pack, 0);
}
+ if (opts.detach > 0) {
+ ret = report_last_gc_error();
+ if (ret == 1) {
+ /* Last gc --auto failed. Skip this one. */
+ ret = 0;
+ goto out;
+
+ } else if (ret) {
+ /* an I/O error occurred, already reported */
+ goto out;
+ }
+
+ if (lock_repo_for_gc(force, &pid)) {
+ ret = 0;
+ goto out;
+ }
+
+ gc_before_repack(&opts, &cfg); /* dies on failure */
+ delete_tempfile(&pidfile);
+
+ /*
+ * failure to daemonize is ok, we'll continue
+ * in foreground
+ */
+ daemonized = !daemonize();
+ }
+
name = lock_repo_for_gc(force, &pid);
if (name) {
- if (opts.auto_flag)
- return 0; /* be quiet on --auto */
+ if (opts.auto_flag) {
+ ret = 0;
+ goto out; /* be quiet on --auto */
+ }
+
die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"),
name, (uintmax_t)pid);
}
@@ -737,11 +810,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
git_path("gc.log"),
LOCK_DIE_ON_ERROR);
dup2(get_lock_file_fd(&log_lock), 2);
- sigchain_push_common(process_log_file_on_signal);
atexit(process_log_file_at_exit);
}
- gc_before_repack(&opts);
+ gc_before_repack(&opts, &cfg);
if (!repository_format_precious_objects) {
struct child_process repack_cmd = CHILD_PROCESS_INIT;
@@ -752,11 +824,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (run_command(&repack_cmd))
die(FAILED_RUN, repack.v[0]);
- if (prune_expire) {
+ if (cfg.prune_expire) {
struct child_process prune_cmd = CHILD_PROCESS_INIT;
/* run `git prune` even if using cruft packs */
- strvec_push(&prune, prune_expire);
+ strvec_push(&prune, cfg.prune_expire);
if (quiet)
strvec_push(&prune, "--no-progress");
if (repo_has_promisor_remote(the_repository))
@@ -769,10 +841,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
}
}
- if (prune_worktrees_expire) {
+ if (cfg.prune_worktrees_expire) {
struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
- strvec_push(&prune_worktrees, prune_worktrees_expire);
+ strvec_push(&prune_worktrees, cfg.prune_worktrees_expire);
prune_worktrees_cmd.git_cmd = 1;
strvec_pushv(&prune_worktrees_cmd.args, prune_worktrees.v);
if (run_command(&prune_worktrees_cmd))
@@ -796,13 +868,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
!quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
NULL);
- if (opts.auto_flag && too_many_loose_objects())
+ if (opts.auto_flag && too_many_loose_objects(&cfg))
warning(_("There are too many unreachable loose objects; "
"run 'git prune' to remove them."));
if (!daemonized)
unlink(git_path("gc.log"));
+out:
+ gc_config_release(&cfg);
return 0;
}
@@ -893,7 +967,7 @@ static int dfs_on_ref(const char *refname UNUSED,
return result;
}
-static int should_write_commit_graph(void)
+static int should_write_commit_graph(struct gc_config *cfg UNUSED)
{
int result;
struct cg_auto_data data;
@@ -930,7 +1004,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts)
return !!run_command(&child);
}
-static int maintenance_task_commit_graph(struct maintenance_run_opts *opts)
+static int maintenance_task_commit_graph(struct maintenance_run_opts *opts,
+ struct gc_config *cfg UNUSED)
{
prepare_repo_settings(the_repository);
if (!the_repository->settings.core_commit_graph)
@@ -964,7 +1039,8 @@ static int fetch_remote(struct remote *remote, void *cbdata)
return !!run_command(&child);
}
-static int maintenance_task_prefetch(struct maintenance_run_opts *opts)
+static int maintenance_task_prefetch(struct maintenance_run_opts *opts,
+ struct gc_config *cfg UNUSED)
{
if (for_each_remote(fetch_remote, opts)) {
error(_("failed to prefetch remotes"));
@@ -974,7 +1050,8 @@ static int maintenance_task_prefetch(struct maintenance_run_opts *opts)
return 0;
}
-static int maintenance_task_gc(struct maintenance_run_opts *opts)
+static int maintenance_task_gc(struct maintenance_run_opts *opts,
+ struct gc_config *cfg UNUSED)
{
struct child_process child = CHILD_PROCESS_INIT;
@@ -987,6 +1064,7 @@ static int maintenance_task_gc(struct maintenance_run_opts *opts)
strvec_push(&child.args, "--quiet");
else
strvec_push(&child.args, "--no-quiet");
+ strvec_push(&child.args, "--no-detach");
return run_command(&child);
}
@@ -1022,7 +1100,7 @@ static int loose_object_count(const struct object_id *oid UNUSED,
return 0;
}
-static int loose_object_auto_condition(void)
+static int loose_object_auto_condition(struct gc_config *cfg UNUSED)
{
int count = 0;
@@ -1082,6 +1160,12 @@ static int pack_loose(struct maintenance_run_opts *opts)
pack_proc.in = -1;
+ /*
+ * git-pack-objects(1) ends up writing the pack hash to stdout, which
+ * we do not care for.
+ */
+ pack_proc.out = -1;
+
if (start_command(&pack_proc)) {
error(_("failed to start 'git pack-objects' process"));
return 1;
@@ -1107,12 +1191,13 @@ static int pack_loose(struct maintenance_run_opts *opts)
return result;
}
-static int maintenance_task_loose_objects(struct maintenance_run_opts *opts)
+static int maintenance_task_loose_objects(struct maintenance_run_opts *opts,
+ struct gc_config *cfg UNUSED)
{
return prune_packed(opts) || pack_loose(opts);
}
-static int incremental_repack_auto_condition(void)
+static int incremental_repack_auto_condition(struct gc_config *cfg UNUSED)
{
struct packed_git *p;
int incremental_repack_auto_limit = 10;
@@ -1231,7 +1316,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts)
return 0;
}
-static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts)
+static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts,
+ struct gc_config *cfg UNUSED)
{
prepare_repo_settings(the_repository);
if (!the_repository->settings.core_multi_pack_index) {
@@ -1248,14 +1334,15 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts
return 0;
}
-typedef int maintenance_task_fn(struct maintenance_run_opts *opts);
+typedef int maintenance_task_fn(struct maintenance_run_opts *opts,
+ struct gc_config *cfg);
/*
* An auto condition function returns 1 if the task should run
* and 0 if the task should NOT run. See needs_to_gc() for an
* example.
*/
-typedef int maintenance_auto_fn(void);
+typedef int maintenance_auto_fn(struct gc_config *cfg);
struct maintenance_task {
const char *name;
@@ -1322,7 +1409,8 @@ static int compare_tasks_by_selection(const void *a_, const void *b_)
return b->selected_order - a->selected_order;
}
-static int maintenance_run_tasks(struct maintenance_run_opts *opts)
+static int maintenance_run_tasks(struct maintenance_run_opts *opts,
+ struct gc_config *cfg)
{
int i, found_selected = 0;
int result = 0;
@@ -1346,6 +1434,13 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
}
free(lock_path);
+ /* Failure to daemonize is ok, we'll continue in foreground. */
+ if (opts->detach > 0) {
+ trace2_region_enter("maintenance", "detach", the_repository);
+ daemonize();
+ trace2_region_leave("maintenance", "detach", the_repository);
+ }
+
for (i = 0; !found_selected && i < TASK__COUNT; i++)
found_selected = tasks[i].selected_order >= 0;
@@ -1361,14 +1456,14 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
if (opts->auto_flag &&
(!tasks[i].auto_condition ||
- !tasks[i].auto_condition()))
+ !tasks[i].auto_condition(cfg)))
continue;
if (opts->schedule && tasks[i].schedule < opts->schedule)
continue;
trace2_region_enter("maintenance", tasks[i].name, r);
- if (tasks[i].fn(opts)) {
+ if (tasks[i].fn(opts, cfg)) {
error(_("task '%s' failed"), tasks[i].name);
result = 1;
}
@@ -1405,7 +1500,6 @@ static void initialize_task_config(int schedule)
{
int i;
struct strbuf config_name = STRBUF_INIT;
- gc_config();
if (schedule)
initialize_maintenance_strategy();
@@ -1468,10 +1562,13 @@ static int task_option_parse(const struct option *opt UNUSED,
static int maintenance_run(int argc, const char **argv, const char *prefix)
{
int i;
- struct maintenance_run_opts opts;
+ struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
+ struct gc_config cfg = GC_CONFIG_INIT;
struct option builtin_maintenance_run_options[] = {
OPT_BOOL(0, "auto", &opts.auto_flag,
N_("run tasks based on the state of the repository")),
+ OPT_BOOL(0, "detach", &opts.detach,
+ N_("perform maintenance in the background")),
OPT_CALLBACK(0, "schedule", &opts.schedule, N_("frequency"),
N_("run tasks based on frequency"),
maintenance_opt_schedule),
@@ -1482,7 +1579,7 @@ static int maintenance_run(int argc, const char **argv, const char *prefix)
PARSE_OPT_NONEG, task_option_parse),
OPT_END()
};
- memset(&opts, 0, sizeof(opts));
+ int ret;
opts.quiet = !isatty(2);
@@ -1497,12 +1594,16 @@ static int maintenance_run(int argc, const char **argv, const char *prefix)
if (opts.auto_flag && opts.schedule)
die(_("use at most one of --auto and --schedule=<frequency>"));
+ gc_config(&cfg);
initialize_task_config(opts.schedule);
if (argc != 0)
usage_with_options(builtin_maintenance_run_usage,
builtin_maintenance_run_options);
- return maintenance_run_tasks(&opts);
+
+ ret = maintenance_run_tasks(&opts, &cfg);
+ gc_config_release(&cfg);
+ return ret;
}
static char *get_maintpath(void)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index fd968d673d..763b01372a 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1868,6 +1868,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
if (!index_name && pack_name)
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
+ /*
+ * Packfiles and indices do not carry enough information to be able to
+ * identify their object hash. So when we are neither in a repository
+ * nor has the user told us which object hash to use we have no other
+ * choice but to guess the object hash.
+ */
+ if (!the_repository->hash_algo)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY);
if (rev_index) {
opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV;
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 1d969494cf..e6f22459f1 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -132,6 +132,7 @@ static void read_input_file(struct strbuf *sb, const char *file)
if (strbuf_read(sb, fileno(stdin), 0) < 0)
die_errno(_("could not read from stdin"));
}
+ strbuf_complete_line(sb);
}
static void interpret_trailers(const struct process_trailer_options *opts,
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 9bca9b5f33..c00469ed3d 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -533,6 +533,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
int expected_remaining_argc;
int original_argc;
const char *merge_base = NULL;
+ int ret;
const char * const merge_tree_usage[] = {
N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"),
@@ -625,7 +626,9 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
strbuf_list_free(split);
}
strbuf_release(&buf);
- return 0;
+
+ ret = 0;
+ goto out;
}
/* Figure out which mode to use */
@@ -664,7 +667,11 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
/* Do the relevant type of merge */
if (o.mode == MODE_REAL)
- return real_merge(&o, merge_base, argv[0], argv[1], prefix);
+ ret = real_merge(&o, merge_base, argv[0], argv[1], prefix);
else
- return trivial_merge(argv[0], argv[1], argv[2]);
+ ret = trivial_merge(argv[0], argv[1], argv[2]);
+
+out:
+ strvec_clear(&xopts);
+ return ret;
}
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ab78d72e27..01479a9ccc 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1072,7 +1072,7 @@ static void write_reused_pack_one(struct packed_git *reuse_packfile,
fixup = find_reused_offset(offset) -
find_reused_offset(base_offset);
if (fixup) {
- unsigned char ofs_header[10];
+ unsigned char ofs_header[MAX_PACK_OBJECT_HEADER];
unsigned i, ofs_len;
off_t ofs = offset - base_offset - fixup;
@@ -1191,6 +1191,7 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile,
size_t pos = (i * BITS_IN_EWORD);
for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
+ uint32_t pack_pos;
if ((word >> offset) == 0)
break;
@@ -1199,14 +1200,41 @@ static void write_reused_pack(struct bitmapped_pack *reuse_packfile,
continue;
if (pos + offset >= reuse_packfile->bitmap_pos + reuse_packfile->bitmap_nr)
goto done;
- /*
- * Can use bit positions directly, even for MIDX
- * bitmaps. See comment in try_partial_reuse()
- * for why.
- */
- write_reused_pack_one(reuse_packfile->p,
- pos + offset - reuse_packfile->bitmap_pos,
- f, pack_start, &w_curs);
+
+ if (reuse_packfile->bitmap_pos) {
+ /*
+ * When doing multi-pack reuse on a
+ * non-preferred pack, translate bit positions
+ * from the MIDX pseudo-pack order back to their
+ * pack-relative positions before attempting
+ * reuse.
+ */
+ struct multi_pack_index *m = reuse_packfile->from_midx;
+ uint32_t midx_pos;
+ off_t pack_ofs;
+
+ if (!m)
+ BUG("non-zero bitmap position without MIDX");
+
+ midx_pos = pack_pos_to_midx(m, pos + offset);
+ pack_ofs = nth_midxed_offset(m, midx_pos);
+
+ if (offset_to_pack_pos(reuse_packfile->p,
+ pack_ofs, &pack_pos) < 0)
+ BUG("could not find expected object at offset %"PRIuMAX" in pack %s",
+ (uintmax_t)pack_ofs,
+ pack_basename(reuse_packfile->p));
+ } else {
+ /*
+ * Can use bit positions directly, even for MIDX
+ * bitmaps. See comment in try_partial_reuse()
+ * for why.
+ */
+ pack_pos = pos + offset;
+ }
+
+ write_reused_pack_one(reuse_packfile->p, pack_pos, f,
+ pack_start, &w_curs);
display_progress(progress_state, ++written);
}
}
@@ -1342,10 +1370,10 @@ static void write_pack_file(void)
if (write_bitmap_index) {
bitmap_writer_init(&bitmap_writer,
- the_repository);
+ the_repository, &to_pack);
bitmap_writer_set_checksum(&bitmap_writer, hash);
bitmap_writer_build_type_index(&bitmap_writer,
- &to_pack, written_list, nr_written);
+ written_list);
}
if (cruft)
@@ -1367,10 +1395,10 @@ static void write_pack_file(void)
bitmap_writer_select_commits(&bitmap_writer,
indexed_commits,
indexed_commits_nr);
- if (bitmap_writer_build(&bitmap_writer, &to_pack) < 0)
+ if (bitmap_writer_build(&bitmap_writer) < 0)
die(_("failed to write bitmap index"));
bitmap_writer_finish(&bitmap_writer,
- written_list, nr_written,
+ written_list,
tmpname.buf, write_bitmap_options);
bitmap_writer_free(&bitmap_writer);
write_bitmap_index = 0;
diff --git a/builtin/remote.c b/builtin/remote.c
index d1f9292ed2..0acc547d69 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -164,6 +164,7 @@ static int add(int argc, const char **argv, const char *prefix)
struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
const char *name, *url;
int i;
+ int result = 0;
struct option options[] = {
OPT_BOOL('f', "fetch", &fetch, N_("fetch the remote branches")),
@@ -230,8 +231,10 @@ static int add(int argc, const char **argv, const char *prefix)
fetch_tags == TAGS_SET ? "--tags" : "--no-tags");
}
- if (fetch && fetch_remote(name))
- return 1;
+ if (fetch && fetch_remote(name)) {
+ result = 1;
+ goto out;
+ }
if (master) {
strbuf_reset(&buf);
@@ -241,14 +244,15 @@ static int add(int argc, const char **argv, const char *prefix)
strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add"))
- return error(_("Could not setup master '%s'"), master);
+ result = error(_("Could not setup master '%s'"), master);
}
+out:
strbuf_release(&buf);
strbuf_release(&buf2);
string_list_clear(&track, 0);
- return 0;
+ return result;
}
struct branch_info {
@@ -715,6 +719,7 @@ static int mv(int argc, const char **argv, const char *prefix)
struct rename_info rename;
int i, refs_renamed_nr = 0, refspec_updated = 0;
struct progress *progress = NULL;
+ int result = 0;
argc = parse_options(argc, argv, prefix, options,
builtin_remote_rename_usage, 0);
@@ -747,9 +752,11 @@ static int mv(int argc, const char **argv, const char *prefix)
strbuf_addf(&buf, "remote.%s", rename.old_name);
strbuf_addf(&buf2, "remote.%s", rename.new_name);
- if (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1)
- return error(_("Could not rename config section '%s' to '%s'"),
- buf.buf, buf2.buf);
+ if (repo_config_rename_section(the_repository, buf.buf, buf2.buf) < 1) {
+ result = error(_("Could not rename config section '%s' to '%s'"),
+ buf.buf, buf2.buf);
+ goto out;
+ }
if (oldremote->fetch.raw_nr) {
strbuf_reset(&buf);
@@ -870,7 +877,7 @@ out:
strbuf_release(&buf);
strbuf_release(&buf2);
strbuf_release(&buf3);
- return 0;
+ return result;
}
static int rm(int argc, const char **argv, const char *prefix)
diff --git a/builtin/repack.c b/builtin/repack.c
index 367e970dcf..3ee8cfa732 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -734,14 +734,23 @@ static void midx_included_packs(struct string_list *include,
struct pack_geometry *geometry)
{
struct string_list_item *item;
+ struct strbuf buf = STRBUF_INIT;
+
+ for_each_string_list_item(item, &existing->kept_packs) {
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "%s.idx", item->string);
+ string_list_insert(include, buf.buf);
+ }
+
+ for_each_string_list_item(item, names) {
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "pack-%s.idx", item->string);
+ string_list_insert(include, buf.buf);
+ }
- for_each_string_list_item(item, &existing->kept_packs)
- string_list_insert(include, xstrfmt("%s.idx", item->string));
- for_each_string_list_item(item, names)
- string_list_insert(include, xstrfmt("pack-%s.idx", item->string));
if (geometry->split_factor) {
- struct strbuf buf = STRBUF_INIT;
uint32_t i;
+
for (i = geometry->split; i < geometry->pack_nr; i++) {
struct packed_git *p = geometry->pack[i];
@@ -756,17 +765,21 @@ static void midx_included_packs(struct string_list *include,
if (!p->pack_local)
continue;
+ strbuf_reset(&buf);
strbuf_addstr(&buf, pack_basename(p));
strbuf_strip_suffix(&buf, ".pack");
strbuf_addstr(&buf, ".idx");
- string_list_insert(include, strbuf_detach(&buf, NULL));
+ string_list_insert(include, buf.buf);
}
} else {
for_each_string_list_item(item, &existing->non_kept_packs) {
if (pack_is_marked_for_deletion(item))
continue;
- string_list_insert(include, xstrfmt("%s.idx", item->string));
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "%s.idx", item->string);
+ string_list_insert(include, buf.buf);
}
}
@@ -786,8 +799,13 @@ static void midx_included_packs(struct string_list *include,
*/
if (pack_is_marked_for_deletion(item))
continue;
- string_list_insert(include, xstrfmt("%s.idx", item->string));
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "%s.idx", item->string);
+ string_list_insert(include, buf.buf);
}
+
+ strbuf_release(&buf);
}
static int write_midx_included_packs(struct string_list *include,
@@ -1478,7 +1496,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
mark_packs_for_deletion(&existing, &names);
if (write_midx) {
- struct string_list include = STRING_LIST_INIT_NODUP;
+ struct string_list include = STRING_LIST_INIT_DUP;
midx_included_packs(&include, &existing, &names, &geometry);
ret = write_midx_included_packs(&include, &geometry, &names,
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 17cae6bbbd..ef0df80824 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -338,5 +338,6 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
free_refs(remote_refs);
free_refs(local_refs);
+ refspec_clear(&rs);
return ret;
}
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 2604ab04df..5ccf696862 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -327,7 +327,6 @@ static int write_patterns_and_update(struct pattern_list *pl)
{
char *sparse_filename;
FILE *fp;
- int fd;
struct lock_file lk = LOCK_INIT;
int result;
@@ -336,31 +335,31 @@ static int write_patterns_and_update(struct pattern_list *pl)
if (safe_create_leading_directories(sparse_filename))
die(_("failed to create directory for sparse-checkout file"));
- fd = hold_lock_file_for_update(&lk, sparse_filename,
- LOCK_DIE_ON_ERROR);
- free(sparse_filename);
+ hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR);
result = update_working_directory(pl);
if (result) {
rollback_lock_file(&lk);
- clear_pattern_list(pl);
update_working_directory(NULL);
- return result;
+ goto out;
}
- fp = xfdopen(fd, "w");
+ fp = fdopen_lock_file(&lk, "w");
+ if (!fp)
+ die_errno(_("unable to fdopen %s"), get_lock_file_path(&lk));
if (core_sparse_checkout_cone)
write_cone_to_file(fp, pl);
else
write_patterns_to_file(fp, pl);
- fflush(fp);
- commit_lock_file(&lk);
+ if (commit_lock_file(&lk))
+ die_errno(_("unable to write %s"), sparse_filename);
+out:
clear_pattern_list(pl);
-
- return 0;
+ free(sparse_filename);
+ return result;
}
enum sparse_checkout_mode {
diff --git a/builtin/stash.c b/builtin/stash.c
index fcfd97972a..be842258d0 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -484,7 +484,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
" to make room.\n"),
ce->name, new_path.buf);
if (rename(ce->name, new_path.buf))
- die("Failed to move %s to %s\n",
+ die("Failed to move %s to %s",
ce->name, new_path.buf);
strbuf_release(&new_path);
}
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 642a0edabf..bf8f9a4012 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -917,7 +917,7 @@ static void generate_submodule_summary(struct summary_cb *info,
} else {
/* for a submodule removal (mode:0000000), don't warn */
if (p->mod_dst)
- warning(_("unexpected mode %o\n"), p->mod_dst);
+ warning(_("unexpected mode %o"), p->mod_dst);
}
}
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 6a6a2ff55d..8f31da9a4b 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -274,7 +274,7 @@ static void parse_cmd_update(struct ref_transaction *transaction,
}
static void parse_cmd_symref_update(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end UNUSED)
{
char *refname, *new_target, *old_arg;
char *old_target = NULL;
@@ -360,7 +360,7 @@ static void parse_cmd_create(struct ref_transaction *transaction,
static void parse_cmd_symref_create(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end UNUSED)
{
struct strbuf err = STRBUF_INIT;
char *refname, *new_target;
@@ -423,7 +423,7 @@ static void parse_cmd_delete(struct ref_transaction *transaction,
static void parse_cmd_symref_delete(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end UNUSED)
{
struct strbuf err = STRBUF_INIT;
char *refname, *old_target;
@@ -479,7 +479,7 @@ static void parse_cmd_verify(struct ref_transaction *transaction,
}
static void parse_cmd_symref_verify(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end UNUSED)
{
struct strbuf err = STRBUF_INIT;
struct object_id old_oid;
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 1b09e5e1aa..313a8dfa81 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -22,6 +22,7 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
{
struct strvec sent_argv = STRVEC_INIT;
const char *arg_cmd = "argument ";
+ int ret;
if (argc != 2 || !strcmp(argv[1], "-h"))
usage(upload_archive_usage);
@@ -46,8 +47,11 @@ int cmd_upload_archive_writer(int argc, const char **argv, const char *prefix)
}
/* parse all options sent by the client */
- return write_archive(sent_argv.nr, sent_argv.v, prefix,
- the_repository, NULL, 1);
+ ret = write_archive(sent_argv.nr, sent_argv.v, prefix,
+ the_repository, NULL, 1);
+
+ strvec_clear(&sent_argv);
+ return ret;
}
__attribute__((format (printf, 1, 2)))