aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/add.c10
-rw-r--r--builtin/am.c37
-rw-r--r--builtin/apply.c7
-rw-r--r--builtin/backfill.c6
-rw-r--r--builtin/blame.c27
-rw-r--r--builtin/bugreport.c4
-rw-r--r--builtin/cat-file.c300
-rw-r--r--builtin/checkout-index.c43
-rw-r--r--builtin/checkout.c19
-rw-r--r--builtin/clone.c34
-rw-r--r--builtin/column.c2
-rw-r--r--builtin/commit-graph.c7
-rw-r--r--builtin/commit-tree.c14
-rw-r--r--builtin/commit.c64
-rw-r--r--builtin/config.c13
-rw-r--r--builtin/count-objects.c2
-rw-r--r--builtin/credential-cache--daemon.c4
-rw-r--r--builtin/describe.c28
-rw-r--r--builtin/diagnose.c4
-rw-r--r--builtin/diff-pairs.c207
-rw-r--r--builtin/diff.c5
-rw-r--r--builtin/difftool.c34
-rw-r--r--builtin/fast-export.c197
-rw-r--r--builtin/fast-import.c38
-rw-r--r--builtin/fetch.c123
-rw-r--r--builtin/fmt-merge-msg.c27
-rw-r--r--builtin/for-each-ref.c5
-rw-r--r--builtin/fsck.c56
-rw-r--r--builtin/gc.c280
-rw-r--r--builtin/grep.c24
-rw-r--r--builtin/hash-object.c60
-rw-r--r--builtin/index-pack.c84
-rw-r--r--builtin/init-db.c16
-rw-r--r--builtin/log.c8
-rw-r--r--builtin/ls-files.c35
-rw-r--r--builtin/ls-remote.c11
-rw-r--r--builtin/ls-tree.c2
-rw-r--r--builtin/merge-file.c1
-rw-r--r--builtin/merge-recursive.c4
-rw-r--r--builtin/merge-tree.c20
-rw-r--r--builtin/merge.c61
-rw-r--r--builtin/mktag.c4
-rw-r--r--builtin/mktree.c5
-rw-r--r--builtin/multi-pack-index.c4
-rw-r--r--builtin/mv.c70
-rw-r--r--builtin/name-rev.c14
-rw-r--r--builtin/notes.c3
-rw-r--r--builtin/pack-objects.c578
-rw-r--r--builtin/pack-redundant.c2
-rw-r--r--builtin/pack-refs.c8
-rw-r--r--builtin/prune.c4
-rw-r--r--builtin/pull.c3
-rw-r--r--builtin/read-tree.c11
-rw-r--r--builtin/rebase.c37
-rw-r--r--builtin/receive-pack.c49
-rw-r--r--builtin/reflog.c221
-rw-r--r--builtin/refs.c2
-rw-r--r--builtin/remote.c7
-rw-r--r--builtin/repack.c79
-rw-r--r--builtin/replace.c4
-rw-r--r--builtin/replay.c65
-rw-r--r--builtin/reset.c6
-rw-r--r--builtin/rev-list.c100
-rw-r--r--builtin/revert.c14
-rw-r--r--builtin/rm.c21
-rw-r--r--builtin/send-pack.c7
-rw-r--r--builtin/show-branch.c15
-rw-r--r--builtin/show-ref.c5
-rw-r--r--builtin/sparse-checkout.c5
-rw-r--r--builtin/stash.c1
-rw-r--r--builtin/submodule--helper.c42
-rw-r--r--builtin/tag.c29
-rw-r--r--builtin/unpack-file.c3
-rw-r--r--builtin/unpack-objects.c12
-rw-r--r--builtin/update-index.c133
-rw-r--r--builtin/update-ref.c83
-rw-r--r--builtin/update-server-info.c4
-rw-r--r--builtin/verify-commit.c13
-rw-r--r--builtin/verify-tag.c7
-rw-r--r--builtin/worktree.c12
-rw-r--r--builtin/write-tree.c12
81 files changed, 2513 insertions, 1104 deletions
diff --git a/builtin/add.c b/builtin/add.c
index 78dfb26577..7c292ffdc6 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -386,11 +386,14 @@ int cmd_add(int argc,
char *ps_matched = NULL;
struct lock_file lock_file = LOCK_INIT;
- if (repo)
- repo_config(repo, add_config, NULL);
+ repo_config(repo, add_config, NULL);
argc = parse_options(argc, argv, prefix, builtin_add_options,
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
+
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
+
if (patch_interactive)
add_interactive = 1;
if (add_interactive) {
@@ -427,9 +430,6 @@ int cmd_add(int argc,
add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
- prepare_repo_settings(repo);
- repo->settings.command_requires_full_index = 0;
-
repo_hold_locked_index(repo, &lock_file, LOCK_DIE_ON_ERROR);
/*
diff --git a/builtin/am.c b/builtin/am.c
index 2921bb89ef..e32a3b4c97 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"
@@ -850,8 +850,10 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
series_dir = dirname(series_dir_buf);
fp = fopen(*paths, "r");
- if (!fp)
+ if (!fp) {
+ free(series_dir_buf);
return error_errno(_("could not open '%s' for reading"), *paths);
+ }
while (!strbuf_getline_lf(&sb, fp)) {
if (*sb.buf == '#')
@@ -1638,12 +1640,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."));
@@ -2399,11 +2402,16 @@ int cmd_am(int argc,
OPT_CMDMODE(0, "quit", &resume_mode,
N_("abort the patching operation but keep HEAD where it is"),
RESUME_QUIT),
- { OPTION_CALLBACK, 0, "show-current-patch", &resume_mode,
- "(diff|raw)",
- N_("show the patch being applied"),
- PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
- parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
+ {
+ .type = OPTION_CALLBACK,
+ .long_name = "show-current-patch",
+ .value = &resume_mode,
+ .argh = "(diff|raw)",
+ .help = N_("show the patch being applied"),
+ .flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+ .callback = parse_opt_show_current_patch,
+ .defval = RESUME_SHOW_PATCH_RAW,
+ },
OPT_CMDMODE(0, "retry", &resume_mode,
N_("try to apply current patch again"),
RESUME_APPLY),
@@ -2416,9 +2424,16 @@ int cmd_am(int argc,
OPT_BOOL(0, "ignore-date", &state.ignore_date,
N_("use current timestamp for author date")),
OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),
- { OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),
- N_("GPG-sign commits"),
- PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &state.sign_commit,
+ .argh = N_("key-id"),
+ .help = N_("GPG-sign commits"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
OPT_CALLBACK_F(0, "empty", &state.empty_type, "(stop|drop|keep)",
N_("how to handle empty patches"),
PARSE_OPT_NONEG, am_option_parse_empty),
diff --git a/builtin/apply.c b/builtin/apply.c
index 84f1863d3a..a1e20c593d 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -12,7 +12,7 @@ static const char * const apply_usage[] = {
int cmd_apply(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int force_apply = 0;
int options = 0;
@@ -35,6 +35,11 @@ int cmd_apply(int argc,
&state, &force_apply, &options,
apply_usage);
+ if (repo) {
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
+ }
+
if (check_apply_state(&state, force_apply))
exit(128);
diff --git a/builtin/backfill.c b/builtin/backfill.c
index 33e1ea2f84..fa82ad2f6f 100644
--- a/builtin/backfill.c
+++ b/builtin/backfill.c
@@ -13,7 +13,7 @@
#include "tree.h"
#include "tree-walk.h"
#include "object.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "oid-array.h"
#include "oidset.h"
#include "promisor-remote.h"
@@ -123,8 +123,8 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
.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_UNSIGNED(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(),
diff --git a/builtin/blame.c b/builtin/blame.c
index c470654c7e..944952e30e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -28,7 +28,7 @@
#include "line-log.h"
#include "progress.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "pager.h"
#include "blame.h"
#include "refs.h"
@@ -36,17 +36,17 @@
#include "tag.h"
#include "write-or-die.h"
-static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
-static char annotate_usage[] = N_("git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>");
+static const char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
+static const char annotate_usage[] = N_("git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>");
-static const char *blame_opt_usage[] = {
+static const char *const blame_opt_usage[] = {
blame_usage,
"",
N_("<rev-opts> are documented in git-rev-list(1)"),
NULL
};
-static const char *annotate_opt_usage[] = {
+static const char *const annotate_opt_usage[] = {
annotate_usage,
"",
N_("<rev-opts> are documented in git-rev-list(1)"),
@@ -351,6 +351,19 @@ static void emit_porcelain_details(struct blame_origin *suspect, int repeat)
write_filename_info(suspect);
}
+/*
+ * Information which needs to be printed per-line goes here. Any
+ * information which can be clubbed on a commit/file level, should
+ * be printed via 'emit_one_suspect_detail()'.
+ */
+static void emit_porcelain_per_line_details(struct blame_entry *ent)
+{
+ if (mark_unblamable_lines && ent->unblamable)
+ puts("unblamable");
+ if (mark_ignored_lines && ent->ignored)
+ puts("ignored");
+}
+
static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
int opt)
{
@@ -367,6 +380,7 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
ent->lno + 1,
ent->num_lines);
emit_porcelain_details(suspect, repeat);
+ emit_porcelain_per_line_details(ent);
cp = blame_nth_line(sb, ent->lno);
for (cnt = 0; cnt < ent->num_lines; cnt++) {
@@ -377,6 +391,7 @@ static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent,
ent->lno + 1 + cnt);
if (repeat)
emit_porcelain_details(suspect, 1);
+ emit_porcelain_per_line_details(ent);
}
putchar('\t');
do {
@@ -929,7 +944,7 @@ int cmd_blame(int argc,
long anchor;
long num_lines = 0;
const char *str_usage = cmd_is_annotate ? annotate_usage : blame_usage;
- const char **opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
+ const char *const *opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
setup_default_color_by_age();
git_config(git_blame_config, &output_option);
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 66d64bfd5a..f78c3f2aed 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -4,13 +4,13 @@
#include "editor.h"
#include "gettext.h"
#include "parse-options.h"
+#include "path.h"
#include "strbuf.h"
#include "help.h"
#include "compat/compiler.h"
#include "hook.h"
#include "hook-list.h"
#include "diagnose.h"
-#include "object-file.h"
#include "setup.h"
#include "version.h"
@@ -141,7 +141,7 @@ int cmd_bugreport(int argc,
}
strbuf_addstr(&report_path, ".txt");
- switch (safe_create_leading_directories(report_path.buf)) {
+ switch (safe_create_leading_directories(the_repository, report_path.buf)) {
case SCLD_OK:
case SCLD_EXISTS:
break;
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index b13561cf73..4b23fcecbd 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -15,14 +15,16 @@
#include "gettext.h"
#include "hex.h"
#include "ident.h"
+#include "list-objects-filter-options.h"
#include "parse-options.h"
#include "userdiff.h"
#include "streaming.h"
#include "oid-array.h"
#include "packfile.h"
+#include "pack-bitmap.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "replace-object.h"
#include "promisor-remote.h"
#include "mailmap.h"
@@ -35,6 +37,7 @@ enum batch_mode {
};
struct batch_options {
+ struct list_objects_filter_options objects_filter;
int enabled;
int follow_symlinks;
enum batch_mode batch_mode;
@@ -97,8 +100,7 @@ static int stream_blob(const struct object_id *oid)
return 0;
}
-static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
- int unknown_type)
+static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
{
int ret;
struct object_id oid;
@@ -107,7 +109,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
unsigned long size;
struct object_context obj_context = {0};
struct object_info oi = OBJECT_INFO_INIT;
- struct strbuf sb = STRBUF_INIT;
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
unsigned get_oid_flags =
GET_OID_RECORD_PATH |
@@ -118,9 +119,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
if (!path && opt_cw)
get_oid_flags |= GET_OID_REQUIRE_PATH;
- if (unknown_type)
- flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
-
if (get_oid_with_context(the_repository, obj_name, get_oid_flags, &oid,
&obj_context))
die("Not a valid object name %s", obj_name);
@@ -133,16 +131,12 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
buf = NULL;
switch (opt) {
case 't':
- oi.type_name = &sb;
+ oi.typep = &type;
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
die("git cat-file: could not get object info");
- if (sb.len) {
- printf("%s\n", sb.buf);
- strbuf_release(&sb);
- ret = 0;
- goto cleanup;
- }
- break;
+ printf("%s\n", type_name(type));
+ ret = 0;
+ goto cleanup;
case 's':
oi.sizep = &size;
@@ -166,7 +160,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
goto cleanup;
case 'e':
- ret = !repo_has_object_file(the_repository, &oid);
+ ret = !has_object(the_repository, &oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR);
goto cleanup;
case 'w':
@@ -280,6 +275,7 @@ struct expand_data {
struct object_id oid;
enum object_type type;
unsigned long size;
+ unsigned short mode;
off_t disk_size;
const char *rest;
struct object_id delta_base_oid;
@@ -311,6 +307,7 @@ struct expand_data {
*/
unsigned skip_object_info : 1;
};
+#define EXPAND_DATA_INIT { .mode = S_IFINVALID }
static int is_atom(const char *atom, const char *s, int slen)
{
@@ -350,6 +347,9 @@ static int expand_atom(struct strbuf *sb, const char *atom, int len,
else
strbuf_addstr(sb,
oid_to_hex(&data->delta_base_oid));
+ } else if (is_atom("objectmode", atom, len)) {
+ if (!data->mark_query && !(S_IFINVALID == data->mode))
+ strbuf_addf(sb, "%06o", data->mode);
} else
return 0;
return 1;
@@ -455,6 +455,16 @@ static void print_default_format(struct strbuf *scratch, struct expand_data *dat
(uintmax_t)data->size, opt->output_delim);
}
+static void report_object_status(struct batch_options *opt,
+ const char *obj_name,
+ const struct object_id *oid,
+ const char *status)
+{
+ printf("%s %s%c", obj_name ? obj_name : oid_to_hex(oid),
+ status, opt->output_delim);
+ fflush(stdout);
+}
+
/*
* If "pack" is non-NULL, then "offset" is the byte offset within the pack from
* which the object may be accessed (though note that we may also rely on
@@ -470,8 +480,13 @@ static void batch_object_write(const char *obj_name,
if (!data->skip_object_info) {
int ret;
- if (use_mailmap)
+ if (use_mailmap ||
+ opt->objects_filter.choice == LOFC_BLOB_NONE ||
+ opt->objects_filter.choice == LOFC_BLOB_LIMIT ||
+ opt->objects_filter.choice == LOFC_OBJECT_TYPE)
data->info.typep = &data->type;
+ if (opt->objects_filter.choice == LOFC_BLOB_LIMIT)
+ data->info.sizep = &data->size;
if (pack)
ret = packed_object_info(the_repository, pack, offset,
@@ -481,12 +496,45 @@ static void batch_object_write(const char *obj_name,
&data->oid, &data->info,
OBJECT_INFO_LOOKUP_REPLACE);
if (ret < 0) {
- printf("%s missing%c",
- obj_name ? obj_name : oid_to_hex(&data->oid), opt->output_delim);
- fflush(stdout);
+ if (data->mode == S_IFGITLINK)
+ report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "submodule");
+ else
+ report_object_status(opt, obj_name, &data->oid, "missing");
return;
}
+ switch (opt->objects_filter.choice) {
+ case LOFC_DISABLED:
+ break;
+ case LOFC_BLOB_NONE:
+ if (data->type == OBJ_BLOB) {
+ if (!opt->all_objects)
+ report_object_status(opt, obj_name,
+ &data->oid, "excluded");
+ return;
+ }
+ break;
+ case LOFC_BLOB_LIMIT:
+ if (data->type == OBJ_BLOB &&
+ data->size >= opt->objects_filter.blob_limit_value) {
+ if (!opt->all_objects)
+ report_object_status(opt, obj_name,
+ &data->oid, "excluded");
+ return;
+ }
+ break;
+ case LOFC_OBJECT_TYPE:
+ if (data->type != opt->objects_filter.object_type) {
+ if (!opt->all_objects)
+ report_object_status(opt, obj_name,
+ &data->oid, "excluded");
+ return;
+ }
+ break;
+ default:
+ BUG("unsupported objects filter");
+ }
+
if (use_mailmap && (data->type == OBJ_COMMIT || data->type == OBJ_TAG)) {
size_t s = data->size;
char *buf = NULL;
@@ -535,10 +583,10 @@ static void batch_one_object(const char *obj_name,
if (result != FOUND) {
switch (result) {
case MISSING_OBJECT:
- printf("%s missing%c", obj_name, opt->output_delim);
+ report_object_status(opt, obj_name, &data->oid, "missing");
break;
case SHORT_NAME_AMBIGUOUS:
- printf("%s ambiguous%c", obj_name, opt->output_delim);
+ report_object_status(opt, obj_name, &data->oid, "ambiguous");
break;
case DANGLING_SYMLINK:
printf("dangling %"PRIuMAX"%c%s%c",
@@ -573,6 +621,7 @@ static void batch_one_object(const char *obj_name,
goto out;
}
+ data->mode = ctx.mode;
batch_object_write(obj_name, scratch, opt, data, NULL, 0);
out:
@@ -595,25 +644,18 @@ static int batch_object_cb(const struct object_id *oid, void *vdata)
return 0;
}
-static int collect_loose_object(const struct object_id *oid,
- const char *path UNUSED,
- void *data)
-{
- oid_array_append(data, oid);
- return 0;
-}
-
-static int collect_packed_object(const struct object_id *oid,
- struct packed_git *pack UNUSED,
- uint32_t pos UNUSED,
- void *data)
+static int collect_object(const struct object_id *oid,
+ struct packed_git *pack UNUSED,
+ off_t offset UNUSED,
+ void *data)
{
oid_array_append(data, oid);
return 0;
}
static int batch_unordered_object(const struct object_id *oid,
- struct packed_git *pack, off_t offset,
+ struct packed_git *pack,
+ off_t offset,
void *vdata)
{
struct object_cb_data *data = vdata;
@@ -627,23 +669,6 @@ static int batch_unordered_object(const struct object_id *oid,
return 0;
}
-static int batch_unordered_loose(const struct object_id *oid,
- const char *path UNUSED,
- void *data)
-{
- return batch_unordered_object(oid, NULL, 0, data);
-}
-
-static int batch_unordered_packed(const struct object_id *oid,
- struct packed_git *pack,
- uint32_t pos,
- void *data)
-{
- return batch_unordered_object(oid, pack,
- nth_packed_object_offset(pack, pos),
- data);
-}
-
typedef void (*parse_cmd_fn_t)(struct batch_options *, const char *,
struct strbuf *, struct expand_data *);
@@ -776,11 +801,81 @@ static void batch_objects_command(struct batch_options *opt,
#define DEFAULT_FORMAT "%(objectname) %(objecttype) %(objectsize)"
+typedef int (*for_each_object_fn)(const struct object_id *oid, struct packed_git *pack,
+ off_t offset, void *data);
+
+struct for_each_object_payload {
+ for_each_object_fn callback;
+ void *payload;
+};
+
+static int batch_one_object_loose(const struct object_id *oid,
+ const char *path UNUSED,
+ void *_payload)
+{
+ struct for_each_object_payload *payload = _payload;
+ return payload->callback(oid, NULL, 0, payload->payload);
+}
+
+static int batch_one_object_packed(const struct object_id *oid,
+ struct packed_git *pack,
+ uint32_t pos,
+ void *_payload)
+{
+ struct for_each_object_payload *payload = _payload;
+ return payload->callback(oid, pack, nth_packed_object_offset(pack, pos),
+ payload->payload);
+}
+
+static int batch_one_object_bitmapped(const struct object_id *oid,
+ enum object_type type UNUSED,
+ int flags UNUSED,
+ uint32_t hash UNUSED,
+ struct packed_git *pack,
+ off_t offset,
+ void *_payload)
+{
+ struct for_each_object_payload *payload = _payload;
+ return payload->callback(oid, pack, offset, payload->payload);
+}
+
+static void batch_each_object(struct batch_options *opt,
+ for_each_object_fn callback,
+ unsigned flags,
+ void *_payload)
+{
+ struct for_each_object_payload payload = {
+ .callback = callback,
+ .payload = _payload,
+ };
+ struct bitmap_index *bitmap = prepare_bitmap_git(the_repository);
+
+ for_each_loose_object(batch_one_object_loose, &payload, 0);
+
+ if (bitmap && !for_each_bitmapped_object(bitmap, &opt->objects_filter,
+ batch_one_object_bitmapped, &payload)) {
+ struct packed_git *pack;
+
+ for (pack = get_all_packs(the_repository); pack; pack = pack->next) {
+ if (bitmap_index_contains_pack(bitmap, pack) ||
+ open_pack_index(pack))
+ continue;
+ for_each_object_in_pack(pack, batch_one_object_packed,
+ &payload, flags);
+ }
+ } else {
+ for_each_packed_object(the_repository, batch_one_object_packed,
+ &payload, flags);
+ }
+
+ free_bitmap_index(bitmap);
+}
+
static int batch_objects(struct batch_options *opt)
{
struct strbuf input = STRBUF_INIT;
struct strbuf output = STRBUF_INIT;
- struct expand_data data;
+ struct expand_data data = EXPAND_DATA_INIT;
int save_warning;
int retval = 0;
@@ -789,7 +884,6 @@ static int batch_objects(struct batch_options *opt)
* object_info to be handed to oid_object_info_extended for each
* object.
*/
- memset(&data, 0, sizeof(data));
data.mark_query = 1;
expand_format(&output,
opt->format ? opt->format : DEFAULT_FORMAT,
@@ -812,7 +906,8 @@ static int batch_objects(struct batch_options *opt)
struct object_cb_data cb;
struct object_info empty = OBJECT_INFO_INIT;
- if (!memcmp(&data.info, &empty, sizeof(empty)))
+ if (!memcmp(&data.info, &empty, sizeof(empty)) &&
+ opt->objects_filter.choice == LOFC_DISABLED)
data.skip_object_info = 1;
if (repo_has_promisor_remote(the_repository))
@@ -829,18 +924,14 @@ static int batch_objects(struct batch_options *opt)
cb.seen = &seen;
- for_each_loose_object(batch_unordered_loose, &cb, 0);
- for_each_packed_object(the_repository, batch_unordered_packed,
- &cb, FOR_EACH_OBJECT_PACK_ORDER);
+ batch_each_object(opt, batch_unordered_object,
+ FOR_EACH_OBJECT_PACK_ORDER, &cb);
oidset_clear(&seen);
} else {
struct oid_array sa = OID_ARRAY_INIT;
- for_each_loose_object(collect_loose_object, &sa, 0);
- for_each_packed_object(the_repository, collect_packed_object,
- &sa, 0);
-
+ batch_each_object(opt, collect_object, 0, &sa);
oid_array_for_each_unique(&sa, batch_object_cb, &cb);
oid_array_clear(&sa);
@@ -936,15 +1027,17 @@ int cmd_cat_file(int argc,
int opt_cw = 0;
int opt_epts = 0;
const char *exp_type = NULL, *obj_name = NULL;
- struct batch_options batch = {0};
+ struct batch_options batch = {
+ .objects_filter = LIST_OBJECTS_FILTER_INIT,
+ };
int unknown_type = 0;
int input_nul_terminated = 0;
int nul_terminated = 0;
+ int ret;
- const char * const usage[] = {
+ const char * const builtin_catfile_usage[] = {
N_("git cat-file <type> <object>"),
- N_("git cat-file (-e | -p) <object>"),
- N_("git cat-file (-t | -s) [--allow-unknown-type] <object>"),
+ N_("git cat-file (-e | -p | -t | -s) <object>"),
N_("git cat-file (--textconv | --filters)\n"
" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"),
N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n"
@@ -962,8 +1055,8 @@ int cmd_cat_file(int argc,
OPT_GROUP(N_("Emit [broken] object attributes")),
OPT_CMDMODE('t', NULL, &opt, N_("show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"), 't'),
OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
- OPT_BOOL(0, "allow-unknown-type", &unknown_type,
- N_("allow -s and -t to work with broken/corrupt objects")),
+ OPT_HIDDEN_BOOL(0, "allow-unknown-type", &unknown_type,
+ N_("historical option -- no-op")),
OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")),
OPT_ALIAS(0, "mailmap", "use-mailmap"),
/* Batch mode */
@@ -1000,6 +1093,7 @@ int cmd_cat_file(int argc,
N_("run filters on object's content"), 'w'),
OPT_STRING(0, "path", &force_path, N_("blob|tree"),
N_("use a <path> for (--textconv | --filters); Not with 'batch'")),
+ OPT_PARSE_LIST_OBJECTS_FILTER(&batch.objects_filter),
OPT_END()
};
@@ -1007,13 +1101,27 @@ int cmd_cat_file(int argc,
batch.buffer_output = -1;
- argc = parse_options(argc, argv, prefix, options, usage, 0);
+ argc = parse_options(argc, argv, prefix, options, builtin_catfile_usage, 0);
opt_cw = (opt == 'c' || opt == 'w');
opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');
if (use_mailmap)
read_mailmap(&mailmap);
+ switch (batch.objects_filter.choice) {
+ case LOFC_DISABLED:
+ break;
+ case LOFC_BLOB_NONE:
+ case LOFC_BLOB_LIMIT:
+ case LOFC_OBJECT_TYPE:
+ if (!batch.enabled)
+ usage(_("objects filter only supported in batch mode"));
+ break;
+ default:
+ usagef(_("objects filter not supported: '%s'"),
+ list_object_filter_config_name(batch.objects_filter.choice));
+ }
+
/* --batch-all-objects? */
if (opt == 'b')
batch.all_objects = 1;
@@ -1021,7 +1129,7 @@ int cmd_cat_file(int argc,
/* Option compatibility */
if (force_path && !opt_cw)
usage_msg_optf(_("'%s=<%s>' needs '%s' or '%s'"),
- usage, options,
+ builtin_catfile_usage, options,
"--path", _("path|tree-ish"), "--filters",
"--textconv");
@@ -1029,20 +1137,20 @@ int cmd_cat_file(int argc,
if (batch.enabled)
;
else if (batch.follow_symlinks)
- usage_msg_optf(_("'%s' requires a batch mode"), usage, options,
- "--follow-symlinks");
+ usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage,
+ options, "--follow-symlinks");
else if (batch.buffer_output >= 0)
- usage_msg_optf(_("'%s' requires a batch mode"), usage, options,
- "--buffer");
+ usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage,
+ options, "--buffer");
else if (batch.all_objects)
- usage_msg_optf(_("'%s' requires a batch mode"), usage, options,
- "--batch-all-objects");
+ usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage,
+ options, "--batch-all-objects");
else if (input_nul_terminated)
- usage_msg_optf(_("'%s' requires a batch mode"), usage, options,
- "-z");
+ usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage,
+ options, "-z");
else if (nul_terminated)
- usage_msg_optf(_("'%s' requires a batch mode"), usage, options,
- "-Z");
+ usage_msg_optf(_("'%s' requires a batch mode"), builtin_catfile_usage,
+ options, "-Z");
batch.input_delim = batch.output_delim = '\n';
if (input_nul_terminated)
@@ -1063,39 +1171,45 @@ int cmd_cat_file(int argc,
batch.transform_mode = opt;
else if (opt && opt != 'b')
usage_msg_optf(_("'-%c' is incompatible with batch mode"),
- usage, options, opt);
+ builtin_catfile_usage, options, opt);
else if (argc)
- usage_msg_opt(_("batch modes take no arguments"), usage,
- options);
+ usage_msg_opt(_("batch modes take no arguments"),
+ builtin_catfile_usage, options);
- return batch_objects(&batch);
+ ret = batch_objects(&batch);
+ goto out;
}
if (opt) {
if (!argc && opt == 'c')
usage_msg_optf(_("<rev> required with '%s'"),
- usage, options, "--textconv");
+ builtin_catfile_usage, options,
+ "--textconv");
else if (!argc && opt == 'w')
usage_msg_optf(_("<rev> required with '%s'"),
- usage, options, "--filters");
+ builtin_catfile_usage, options,
+ "--filters");
else if (!argc && opt_epts)
usage_msg_optf(_("<object> required with '-%c'"),
- usage, options, opt);
+ builtin_catfile_usage, options, opt);
else if (argc == 1)
obj_name = argv[0];
else
- usage_msg_opt(_("too many arguments"), usage, options);
+ usage_msg_opt(_("too many arguments"), builtin_catfile_usage,
+ options);
} else if (!argc) {
- usage_with_options(usage, options);
+ usage_with_options(builtin_catfile_usage, options);
} else if (argc != 2) {
usage_msg_optf(_("only two arguments allowed in <type> <object> mode, not %d"),
- usage, options, argc);
+ builtin_catfile_usage, options, argc);
} else if (argc) {
exp_type = argv[0];
obj_name = argv[1];
}
- if (unknown_type && opt != 't' && opt != 's')
- die("git cat-file --allow-unknown-type: use with -s or -t");
- return cat_one_file(opt, exp_type, obj_name, unknown_type);
+ ret = cat_one_file(opt, exp_type, obj_name);
+
+out:
+ list_objects_filter_release(&batch.objects_filter);
+ return ret;
}
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index e30086c7d4..7f74bc702f 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -5,7 +5,6 @@
*
*/
-#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "builtin.h"
@@ -68,10 +67,10 @@ static void write_tempfile_record(const char *name, const char *prefix)
}
}
-static int checkout_file(const char *name, const char *prefix)
+static int checkout_file(struct index_state *index, const char *name, const char *prefix)
{
int namelen = strlen(name);
- int pos = index_name_pos(the_repository->index, name, namelen);
+ int pos = index_name_pos(index, name, namelen);
int has_same_name = 0;
int is_file = 0;
int is_skipped = 1;
@@ -81,8 +80,8 @@ static int checkout_file(const char *name, const char *prefix)
if (pos < 0)
pos = -pos - 1;
- while (pos <the_repository->index->cache_nr) {
- struct cache_entry *ce =the_repository->index->cache[pos];
+ while (pos < index->cache_nr) {
+ struct cache_entry *ce = index->cache[pos];
if (ce_namelen(ce) != namelen ||
memcmp(ce->name, name, namelen))
break;
@@ -137,13 +136,13 @@ static int checkout_file(const char *name, const char *prefix)
return -1;
}
-static int checkout_all(const char *prefix, int prefix_length)
+static int checkout_all(struct index_state *index, const char *prefix, int prefix_length)
{
int i, errs = 0;
struct cache_entry *last_ce = NULL;
- for (i = 0; i < the_repository->index->cache_nr ; i++) {
- struct cache_entry *ce = the_repository->index->cache[i];
+ for (i = 0; i < index->cache_nr ; i++) {
+ struct cache_entry *ce = index->cache[i];
if (S_ISSPARSEDIR(ce->ce_mode)) {
if (!ce_skip_worktree(ce))
@@ -156,8 +155,8 @@ static int checkout_all(const char *prefix, int prefix_length)
* first entry inside the expanded sparse directory).
*/
if (ignore_skip_worktree) {
- ensure_full_index(the_repository->index);
- ce = the_repository->index->cache[i];
+ ensure_full_index(index);
+ ce = index->cache[i];
}
}
@@ -213,7 +212,7 @@ static int option_parse_stage(const struct option *opt,
int cmd_checkout_index(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int i;
struct lock_file lock_file = LOCK_INIT;
@@ -253,19 +252,19 @@ int cmd_checkout_index(int argc,
show_usage_with_options_if_asked(argc, argv,
builtin_checkout_index_usage,
builtin_checkout_index_options);
- git_config(git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
prefix_length = prefix ? strlen(prefix) : 0;
- prepare_repo_settings(the_repository);
- the_repository->settings.command_requires_full_index = 0;
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
- if (repo_read_index(the_repository) < 0) {
+ if (repo_read_index(repo) < 0) {
die("invalid cache");
}
argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
builtin_checkout_index_usage, 0);
- state.istate = the_repository->index;
+ state.istate = repo->index;
state.force = force;
state.quiet = quiet;
state.not_new = not_new;
@@ -285,8 +284,8 @@ int cmd_checkout_index(int argc,
*/
if (index_opt && !state.base_dir_len && !to_tempfile) {
state.refresh_cache = 1;
- state.istate = the_repository->index;
- repo_hold_locked_index(the_repository, &lock_file,
+ state.istate = repo->index;
+ repo_hold_locked_index(repo, &lock_file,
LOCK_DIE_ON_ERROR);
}
@@ -304,7 +303,7 @@ int cmd_checkout_index(int argc,
if (read_from_stdin)
die("git checkout-index: don't mix '--stdin' and explicit filenames");
p = prefix_path(prefix, prefix_length, arg);
- err |= checkout_file(p, prefix);
+ err |= checkout_file(repo->index, p, prefix);
free(p);
}
@@ -326,7 +325,7 @@ int cmd_checkout_index(int argc,
strbuf_swap(&buf, &unquoted);
}
p = prefix_path(prefix, prefix_length, buf.buf);
- err |= checkout_file(p, prefix);
+ err |= checkout_file(repo->index, p, prefix);
free(p);
}
strbuf_release(&unquoted);
@@ -334,7 +333,7 @@ int cmd_checkout_index(int argc,
}
if (all)
- err |= checkout_all(prefix, prefix_length);
+ err |= checkout_all(repo->index, prefix, prefix_length);
if (pc_workers > 1)
err |= run_parallel_checkout(&state, pc_workers, pc_threshold,
@@ -344,7 +343,7 @@ int cmd_checkout_index(int argc,
return 1;
if (is_lock_file_locked(&lock_file) &&
- write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
+ write_locked_index(repo->index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
return 0;
}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 01ea9ff8b2..d185982f3a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -17,9 +17,10 @@
#include "merge-ll.h"
#include "lockfile.h"
#include "mem-pool.h"
-#include "merge-recursive.h"
+#include "merge-ort-wrappers.h"
+#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "parse-options.h"
#include "path.h"
#include "preload-index.h"
@@ -130,8 +131,8 @@ static int post_checkout_hook(struct commit *old_commit, struct commit *new_comm
int changed)
{
return run_hooks_l(the_repository, "post-checkout",
- oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),
- oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
+ oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),
+ oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),
changed ? "1" : "0", NULL);
/* "new_commit" can be NULL when checking out from the index before
a commit exists. */
@@ -710,7 +711,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
opts.src_index = the_repository->index;
opts.dst_index = the_repository->index;
init_checkout_metadata(&opts.meta, info->refname,
- info->commit ? &info->commit->object.oid : null_oid(),
+ info->commit ? &info->commit->object.oid : null_oid(the_hash_algo),
NULL);
if (parse_tree(tree) < 0)
return 128;
@@ -907,10 +908,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
o.branch1 = new_branch_info->name;
o.branch2 = "local";
o.conflict_style = opts->conflict_style;
- ret = merge_trees(&o,
- new_tree,
- work,
- old_tree);
+ ret = merge_ort_nonrecursive(&o,
+ new_tree,
+ work,
+ old_tree);
if (ret < 0)
exit(128);
ret = reset_tree(new_tree,
diff --git a/builtin/clone.c b/builtin/clone.c
index f14229abf4..91b9cd0d16 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -25,7 +25,7 @@
#include "refs.h"
#include "refspec.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "tree.h"
#include "tree-walk.h"
#include "unpack-trees.h"
@@ -342,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
strbuf_setlen(src, src_len);
die(_("failed to iterate over '%s'"), src->buf);
}
+
+ dir_iterator_free(iter);
}
static void clone_local(const char *src_repo, const char *dest_repo)
@@ -450,7 +452,9 @@ static struct ref *wanted_peer_refs(struct clone_opts *opts,
if (head)
tail_link_ref(head, &tail);
if (option_single_branch)
- refs = to_free = guess_remote_head(head, refs, 0);
+ refs = to_free =
+ guess_remote_head(head, refs,
+ REMOTE_GUESS_HEAD_QUIET);
} else if (option_single_branch) {
local_refs = NULL;
tail = &local_refs;
@@ -500,9 +504,7 @@ static void write_followtags(const struct ref *refs, const char *msg)
continue;
if (ends_with(ref->name, "^{}"))
continue;
- if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid,
- OBJECT_INFO_QUICK |
- OBJECT_INFO_SKIP_FETCH_OBJECT))
+ if (!has_object(the_repository, &ref->old_oid, 0))
continue;
refs_update_ref(get_main_ref_store(the_repository), msg,
ref->name, &ref->old_oid, NULL, 0,
@@ -690,7 +692,7 @@ static int checkout(int submodule_progress, int filter_submodules,
if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
- err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid()),
+ err |= run_hooks_l(the_repository, "post-checkout", oid_to_hex(null_oid(the_hash_algo)),
oid_to_hex(&oid), "1", NULL);
if (!err && (option_recurse_submodules.nr > 0)) {
@@ -928,9 +930,16 @@ int cmd_clone(int argc,
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)"." },
+ {
+ .type = OPTION_CALLBACK,
+ .long_name = "recurse-submodules",
+ .value = &option_recurse_submodules,
+ .argh = N_("pathspec"),
+ .help = N_("initialize submodules in the clone"),
+ .flags = PARSE_OPT_OPTARG,
+ .callback = recurse_submodules_cb,
+ .defval = (intptr_t)".",
+ },
OPT_ALIAS(0, "recursive", "recurse-submodules"),
OPT_INTEGER('j', "jobs", &max_jobs,
N_("number of submodules cloned in parallel")),
@@ -1088,7 +1097,7 @@ int cmd_clone(int argc,
sigchain_push_common(remove_junk_on_signal);
if (!option_bare) {
- if (safe_create_leading_directories_const(work_tree) < 0)
+ if (safe_create_leading_directories_const(the_repository, work_tree) < 0)
die_errno(_("could not create leading directories of '%s'"),
work_tree);
if (dest_exists)
@@ -1109,7 +1118,7 @@ int cmd_clone(int argc,
junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
junk_git_dir = git_dir;
}
- if (safe_create_leading_directories_const(git_dir) < 0)
+ if (safe_create_leading_directories_const(the_repository, git_dir) < 0)
die(_("could not create leading directories of '%s'"), git_dir);
if (0 <= option_verbosity) {
@@ -1523,7 +1532,8 @@ int cmd_clone(int argc,
}
remote_head = find_ref_by_name(refs, "HEAD");
- remote_head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
+ remote_head_points_at = guess_remote_head(remote_head, mapped_refs,
+ REMOTE_GUESS_HEAD_QUIET);
if (option_branch) {
our_head_points_at = find_remote_branch(mapped_refs, option_branch);
diff --git a/builtin/column.c b/builtin/column.c
index 50314cc255..ce6443d5fa 100644
--- a/builtin/column.c
+++ b/builtin/column.c
@@ -31,7 +31,7 @@ int cmd_column(int argc,
struct option options[] = {
OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")),
OPT_COLUMN(0, "mode", &colopts, N_("layout to use")),
- OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")),
+ OPT_UNSIGNED(0, "raw-mode", &colopts, N_("layout to use")),
OPT_INTEGER(0, "width", &copts.width, N_("maximum width")),
OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("padding space on left border")),
OPT_STRING(0, "nl", &copts.nl, N_("string"), N_("padding space on right border")),
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 8ca75262c5..ee48980248 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -6,7 +6,7 @@
#include "hex.h"
#include "parse-options.h"
#include "commit-graph.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "progress.h"
#include "replace-object.h"
#include "strbuf.h"
@@ -22,12 +22,12 @@
" [--changed-paths] [--[no-]max-new-filters <n>] [--[no-]progress]\n" \
" <split-options>")
-static const char * builtin_commit_graph_verify_usage[] = {
+static const char * const builtin_commit_graph_verify_usage[] = {
BUILTIN_COMMIT_GRAPH_VERIFY_USAGE,
NULL
};
-static const char * builtin_commit_graph_write_usage[] = {
+static const char * const builtin_commit_graph_write_usage[] = {
BUILTIN_COMMIT_GRAPH_WRITE_USAGE,
NULL
};
@@ -311,6 +311,7 @@ static int graph_write(int argc, const char **argv, const char *prefix,
while (strbuf_getline(&buf, stdin) != EOF) {
if (read_one_commit(&commits, progress, buf.buf)) {
result = 1;
+ stop_progress(&progress);
goto cleanup;
}
}
diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
index 38457600a4..ad6b2c9320 100644
--- a/builtin/commit-tree.c
+++ b/builtin/commit-tree.c
@@ -9,7 +9,7 @@
#include "gettext.h"
#include "hex.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "commit.h"
#include "parse-options.h"
@@ -111,8 +111,16 @@ int cmd_commit_tree(int argc,
OPT_CALLBACK_F('F', NULL, &buffer, N_("file"),
N_("read commit log message from file"), PARSE_OPT_NONEG,
parse_file_arg_callback),
- { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
- N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &sign_commit,
+ .argh = N_("key-id"),
+ .help = N_("GPG sign commit"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
OPT_END()
};
int ret;
diff --git a/builtin/commit.c b/builtin/commit.c
index 2f45968222..fba0dded64 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1022,7 +1022,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
for (i = 0; i < the_repository->index->cache_nr; i++)
if (ce_intent_to_add(the_repository->index->cache[i]))
ita_nr++;
- committable = the_repository->index->cache_nr - ita_nr > 0;
+ committable = the_repository->index->cache_nr > ita_nr;
} else {
/*
* Unless the user did explicitly request a submodule
@@ -1542,17 +1542,34 @@ struct repository *repo UNUSED)
STATUS_FORMAT_LONG),
OPT_BOOL('z', "null", &s.null_termination,
N_("terminate entries with NUL")),
- { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
- N_("mode"),
- N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
- { OPTION_STRING, 0, "ignored", &ignored_arg,
- N_("mode"),
- N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
- { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
- N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'u',
+ .long_name = "untracked-files",
+ .value = &untracked_files_arg,
+ .argh = N_("mode"),
+ .help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t)"all",
+ },
+ {
+ .type = OPTION_STRING,
+ .long_name = "ignored",
+ .value = &ignored_arg,
+ .argh = N_("mode"),
+ .help = N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t)"traditional",
+ },
+ {
+ .type = OPTION_STRING,
+ .long_name = "ignore-submodules",
+ .value = &ignore_submodule_arg,
+ .argh = N_("when"),
+ .help = N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t)"all",
+ },
OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
OPT_CALLBACK_F('M', "find-renames", &rename_score_arg,
@@ -1688,8 +1705,16 @@ int cmd_commit(int argc,
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
OPT_CLEANUP(&cleanup_arg),
OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
- { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
- N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &sign_commit,
+ .argh = N_("key-id"),
+ .help = N_("GPG sign commit"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
/* end commit message options */
OPT_GROUP(N_("Commit contents options")),
@@ -1714,7 +1739,16 @@ int cmd_commit(int argc,
N_("terminate entries with NUL")),
OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
- { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'u',
+ .long_name = "untracked-files",
+ .value = &untracked_files_arg,
+ .argh = N_("mode"),
+ .help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t)"all",
+ },
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
/* end commit contents options */
diff --git a/builtin/config.c b/builtin/config.c
index 53a90094e3..f70d635477 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -131,9 +131,16 @@ struct config_display_options {
#define TYPE_COLOR 6
#define TYPE_BOOL_OR_STR 7
-#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
- { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
- PARSE_OPT_NONEG, option_parse_type, (i) }
+#define OPT_CALLBACK_VALUE(s, l, v, h, i) { \
+ .type = OPTION_CALLBACK, \
+ .short_name = (s), \
+ .long_name = (l), \
+ .value = (v), \
+ .help = (h), \
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
+ .callback = option_parse_type, \
+ .defval = (i), \
+}
static int option_parse_type(const struct option *opt, const char *arg,
int unset)
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index 1e89148ed7..a88c0c9c09 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -12,7 +12,7 @@
#include "parse-options.h"
#include "quote.h"
#include "packfile.h"
-#include "object-store-ll.h"
+#include "object-file.h"
static unsigned long garbage;
static off_t size_garbage;
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index e707618e74..5065ff4660 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -2,8 +2,8 @@
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
+#include "path.h"
#ifndef NO_UNIX_SOCKETS
@@ -271,7 +271,7 @@ static void init_socket_directory(const char *path)
* condition in which somebody can chdir to it, sleep, then try to open
* our protected socket.
*/
- if (safe_create_leading_directories_const(dir) < 0)
+ if (safe_create_leading_directories_const(the_repository, dir) < 0)
die_errno("unable to create directories for '%s'", dir);
if (mkdir(dir, 0700) < 0)
die_errno("unable to mkdir '%s'", dir);
diff --git a/builtin/describe.c b/builtin/describe.c
index e2e73f3d75..2d50883b72 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -19,7 +19,7 @@
#include "setup.h"
#include "strvec.h"
#include "run-command.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "list-objects.h"
#include "commit-slab.h"
#include "wildmatch.h"
@@ -518,7 +518,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)
{
struct rev_info revs;
struct strvec args = STRVEC_INIT;
- struct process_commit_data pcd = { *null_oid(), oid, dst, &revs};
+ struct process_commit_data pcd = { *null_oid(the_hash_algo), oid, dst, &revs};
strvec_pushl(&args, "internal: The first arg is not parsed",
"--objects", "--in-commit-order", "--reverse", "HEAD",
@@ -601,12 +601,24 @@ int cmd_describe(int argc,
N_("do not consider tags matching <pattern>")),
OPT_BOOL(0, "always", &always,
N_("show abbreviated commit object as fallback")),
- {OPTION_STRING, 0, "dirty", &dirty, N_("mark"),
- N_("append <mark> on dirty working tree (default: \"-dirty\")"),
- PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
- {OPTION_STRING, 0, "broken", &broken, N_("mark"),
- N_("append <mark> on broken working tree (default: \"-broken\")"),
- PARSE_OPT_OPTARG, NULL, (intptr_t) "-broken"},
+ {
+ .type = OPTION_STRING,
+ .long_name = "dirty",
+ .value = &dirty,
+ .argh = N_("mark"),
+ .help = N_("append <mark> on dirty working tree (default: \"-dirty\")"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "-dirty",
+ },
+ {
+ .type = OPTION_STRING,
+ .long_name = "broken",
+ .value = &broken,
+ .argh = N_("mark"),
+ .help = N_("append <mark> on broken working tree (default: \"-broken\")"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "-broken",
+ },
OPT_END(),
};
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index 33c39bd598..ec86d66389 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -3,8 +3,8 @@
#include "builtin.h"
#include "abspath.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
+#include "path.h"
#include "diagnose.h"
static const char * const diagnose_usage[] = {
@@ -50,7 +50,7 @@ int cmd_diagnose(int argc,
strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0);
strbuf_addstr(&zip_path, ".zip");
- switch (safe_create_leading_directories(zip_path.buf)) {
+ switch (safe_create_leading_directories(the_repository, zip_path.buf)) {
case SCLD_OK:
case SCLD_EXISTS:
break;
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.c b/builtin/diff.c
index a4fffee42c..fa963808c3 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -104,7 +104,7 @@ static void builtin_diff_b_f(struct rev_info *revs,
stuff_change(&revs->diffopt,
blob[0]->mode, canon_mode(st.st_mode),
- &blob[0]->item->oid, null_oid(),
+ &blob[0]->item->oid, null_oid(the_hash_algo),
1, 0,
blob[0]->path ? blob[0]->path : path,
path);
@@ -498,7 +498,8 @@ int cmd_diff(int argc,
/* If this is a no-index diff, just run it and exit there. */
if (no_index)
- exit(diff_no_index(&rev, no_index == DIFF_NO_INDEX_IMPLICIT,
+ exit(diff_no_index(&rev, the_repository->hash_algo,
+ no_index == DIFF_NO_INDEX_IMPLICIT,
argc, argv));
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 41cd00066c..a3b64ce694 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -22,6 +22,7 @@
#include "gettext.h"
#include "hex.h"
#include "parse-options.h"
+#include "path.h"
#include "read-cache-ll.h"
#include "repository.h"
#include "sparse-index.h"
@@ -29,7 +30,7 @@
#include "strbuf.h"
#include "lockfile.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "dir.h"
#include "entry.h"
#include "setup.h"
@@ -271,9 +272,9 @@ static void changed_files(struct repository *repo,
strbuf_release(&buf);
}
-static int ensure_leading_directories(char *path)
+static int ensure_leading_directories(struct repository *repo, char *path)
{
- switch (safe_create_leading_directories(path)) {
+ switch (safe_create_leading_directories(repo, path)) {
case SCLD_OK:
case SCLD_EXISTS:
return 0;
@@ -341,11 +342,12 @@ static int checkout_path(unsigned mode, struct object_id *oid,
return ret;
}
-static void write_file_in_directory(struct strbuf *dir, size_t dir_len,
- const char *path, const char *content)
+static void write_file_in_directory(struct repository *repo,
+ struct strbuf *dir, size_t dir_len,
+ const char *path, const char *content)
{
add_path(dir, dir_len, path);
- ensure_leading_directories(dir->buf);
+ ensure_leading_directories(repo, dir->buf);
unlink(dir->buf);
write_file(dir->buf, "%s", content);
}
@@ -356,14 +358,15 @@ static void write_file_in_directory(struct strbuf *dir, size_t dir_len,
* as text files, resulting in behavior that is analogous to what "git diff"
* displays for symlink and submodule diffs.
*/
-static void write_standin_files(struct pair_entry *entry,
- struct strbuf *ldir, size_t ldir_len,
- struct strbuf *rdir, size_t rdir_len)
+static void write_standin_files(struct repository *repo,
+ struct pair_entry *entry,
+ struct strbuf *ldir, size_t ldir_len,
+ struct strbuf *rdir, size_t rdir_len)
{
if (*entry->left)
- write_file_in_directory(ldir, ldir_len, entry->path, entry->left);
+ write_file_in_directory(repo, ldir, ldir_len, entry->path, entry->left);
if (*entry->right)
- write_file_in_directory(rdir, rdir_len, entry->path, entry->right);
+ write_file_in_directory(repo, rdir, rdir_len, entry->path, entry->right);
}
static int run_dir_diff(struct repository *repo,
@@ -533,7 +536,7 @@ static int run_dir_diff(struct repository *repo,
ADD_CACHE_JUST_APPEND);
add_path(&rdir, rdir_len, dst_path);
- if (ensure_leading_directories(rdir.buf)) {
+ if (ensure_leading_directories(repo, rdir.buf)) {
ret = error("could not create "
"directory for '%s'",
dst_path);
@@ -576,7 +579,7 @@ static int run_dir_diff(struct repository *repo,
*/
hashmap_for_each_entry(&submodules, &iter, entry,
entry /* member name */) {
- write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len);
+ write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len);
}
/*
@@ -587,7 +590,7 @@ static int run_dir_diff(struct repository *repo,
hashmap_for_each_entry(&symlinks2, &iter, entry,
entry /* member name */) {
- write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len);
+ write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len);
}
strbuf_setlen(&ldir, ldir_len);
@@ -750,8 +753,7 @@ int cmd_difftool(int argc,
};
struct child_process child = CHILD_PROCESS_INIT;
- if (repo)
- repo_config(repo, difftool_config, &dt_options);
+ repo_config(repo, difftool_config, &dt_options);
dt_options.symlinks = dt_options.has_symlinks;
argc = parse_options(argc, argv, prefix, builtin_difftool_options,
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index a5c82eef1d..fcf6b00d5f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -14,7 +14,7 @@
#include "refs.h"
#include "refspec.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "commit.h"
#include "object.h"
#include "tag.h"
@@ -30,13 +30,16 @@
#include "remote.h"
#include "blob.h"
-static const char *fast_export_usage[] = {
+static const char *const fast_export_usage[] = {
N_("git fast-export [<rev-list-opts>]"),
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_STRIP;
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",
@@ -869,7 +949,7 @@ static void handle_tag(const char *name, struct tag *tag)
p = rewrite_commit((struct commit *)tagged);
if (!p) {
printf("reset %s\nfrom %s\n\n",
- name, oid_to_hex(null_oid()));
+ name, oid_to_hex(null_oid(the_hash_algo)));
free(buf);
return;
}
@@ -883,7 +963,7 @@ static void handle_tag(const char *name, struct tag *tag)
if (tagged->type == OBJ_TAG) {
printf("reset %s\nfrom %s\n\n",
- name, oid_to_hex(null_oid()));
+ name, oid_to_hex(null_oid(the_hash_algo)));
}
skip_prefix(name, "refs/tags/", &name);
printf("tag %s\n", name);
@@ -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:
@@ -1023,7 +1103,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)
* it.
*/
printf("reset %s\nfrom %s\n\n",
- name, oid_to_hex(null_oid()));
+ name, oid_to_hex(null_oid(the_hash_algo)));
continue;
}
@@ -1042,7 +1122,7 @@ static void handle_tags_and_duplicates(struct string_list *extras)
if (!reference_excluded_commits) {
/* delete the ref */
printf("reset %s\nfrom %s\n\n",
- name, oid_to_hex(null_oid()));
+ name, oid_to_hex(null_oid(the_hash_algo)));
continue;
}
/* set ref to commit using oid, not mark */
@@ -1153,7 +1233,7 @@ static void handle_deletes(void)
continue;
printf("reset %s\nfrom %s\n\n",
- refspec->dst, oid_to_hex(null_oid()));
+ refspec->dst, oid_to_hex(null_oid(the_hash_algo)));
}
}
@@ -1202,7 +1282,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),
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 397a6f46ad..b2839c5f43 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -24,7 +24,7 @@
#include "packfile.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "mem-pool.h"
#include "commit-reach.h"
#include "khash.h"
@@ -770,7 +770,7 @@ static void start_packfile(void)
p->pack_fd = pack_fd;
p->do_not_close = 1;
p->repo = the_repository;
- pack_file = hashfd(pack_fd, p->pack_name);
+ pack_file = hashfd(the_repository->hash_algo, pack_fd, p->pack_name);
pack_data = p;
pack_size = write_pack_header(pack_file, 0);
@@ -798,7 +798,7 @@ static const char *create_index(void)
if (c != last)
die("internal consistency error creating the index");
- tmpfile = write_idx_file(the_hash_algo, NULL, idx, object_count,
+ tmpfile = write_idx_file(the_repository, NULL, idx, object_count,
&pack_idx_opts, pack_data->hash);
free(idx);
return tmpfile;
@@ -811,7 +811,8 @@ static char *keep_pack(const char *curr_index_name)
int keep_fd;
odb_pack_name(pack_data->repo, &name, pack_data->hash, "keep");
- keep_fd = odb_pack_keep(name.buf);
+ keep_fd = safe_create_file_with_leading_directories(pack_data->repo,
+ name.buf);
if (keep_fd < 0)
die_errno("cannot create keep file");
write_or_die(keep_fd, keep_msg, strlen(keep_msg));
@@ -1720,7 +1721,7 @@ static void dump_marks(void)
if (!export_marks_file || (import_marks_file && !import_marks_file_done))
return;
- if (safe_create_leading_directories_const(export_marks_file)) {
+ if (safe_create_leading_directories_const(the_repository, export_marks_file)) {
failure |= error_errno("unable to create leading directories of %s",
export_marks_file);
return;
@@ -2021,7 +2022,7 @@ static void parse_and_store_blob(
static struct strbuf buf = STRBUF_INIT;
uintmax_t len;
- if (parse_data(&buf, big_file_threshold, &len))
+ if (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))
store_object(OBJ_BLOB, &buf, last, oidout, mark);
else {
if (last) {
@@ -2719,10 +2720,13 @@ static struct hash_list *parse_merge(unsigned int *count)
static void parse_new_commit(const char *arg)
{
+ static struct strbuf sig = STRBUF_INIT;
static struct strbuf msg = STRBUF_INIT;
+ struct string_list siglines = STRING_LIST_INIT_NODUP;
struct branch *b;
char *author = NULL;
char *committer = NULL;
+ char *sig_alg = NULL;
char *encoding = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
@@ -2746,6 +2750,13 @@ static void parse_new_commit(const char *arg)
}
if (!committer)
die("Expected committer but didn't get one");
+ if (skip_prefix(command_buf.buf, "gpgsig ", &v)) {
+ sig_alg = xstrdup(v);
+ read_next_command();
+ parse_data(&sig, 0, NULL);
+ read_next_command();
+ } else
+ strbuf_setlen(&sig, 0);
if (skip_prefix(command_buf.buf, "encoding ", &v)) {
encoding = xstrdup(v);
read_next_command();
@@ -2819,10 +2830,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))
@@ -3402,7 +3426,7 @@ static int parse_one_option(const char *option)
unsigned long v;
if (!git_parse_ulong(option, &v))
return 0;
- big_file_threshold = v;
+ repo_settings_set_big_file_threshold(the_repository, v);
} else if (skip_prefix(option, "depth=", &option)) {
option_depth(option);
} else if (skip_prefix(option, "active-branches=", &option)) {
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 95fd0018b9..40a0e8d244 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -14,7 +14,7 @@
#include "refs.h"
#include "refspec.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "oidset.h"
#include "oid-array.h"
#include "commit.h"
@@ -337,7 +337,6 @@ static void find_non_local_tags(const struct ref *refs,
struct string_list_item *remote_ref_item;
const struct ref *ref;
struct refname_hash_entry *item = NULL;
- const int quick_flags = OBJECT_INFO_QUICK | OBJECT_INFO_SKIP_FETCH_OBJECT;
refname_hash_init(&existing_refs);
refname_hash_init(&remote_refs);
@@ -367,9 +366,9 @@ static void find_non_local_tags(const struct ref *refs,
*/
if (ends_with(ref->name, "^{}")) {
if (item &&
- !repo_has_object_file_with_flags(the_repository, &ref->old_oid, quick_flags) &&
+ !has_object(the_repository, &ref->old_oid, 0) &&
!oidset_contains(&fetch_oids, &ref->old_oid) &&
- !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
+ !has_object(the_repository, &item->oid, 0) &&
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
item = NULL;
@@ -383,7 +382,7 @@ static void find_non_local_tags(const struct ref *refs,
* fetch.
*/
if (item &&
- !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
+ !has_object(the_repository, &item->oid, 0) &&
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
@@ -404,7 +403,7 @@ static void find_non_local_tags(const struct ref *refs,
* checked to see if it needs fetching.
*/
if (item &&
- !repo_has_object_file_with_flags(the_repository, &item->oid, quick_flags) &&
+ !has_object(the_repository, &item->oid, 0) &&
!oidset_contains(&fetch_oids, &item->oid))
clear_item(item);
@@ -586,7 +585,7 @@ static struct ref *get_ref_map(struct remote *remote,
struct refspec_item tag_refspec;
/* also fetch all tags */
- refspec_item_init(&tag_refspec, TAG_REFSPEC, 0);
+ refspec_item_init_push(&tag_refspec, TAG_REFSPEC);
get_fetch_map(remote_refs, &tag_refspec, &tail, 0);
refspec_item_clear(&tag_refspec);
} else if (tags == TAGS_DEFAULT && *autotags) {
@@ -687,7 +686,7 @@ static int s_update_ref(const char *action,
switch (ref_transaction_commit(our_transaction, &err)) {
case 0:
break;
- case TRANSACTION_NAME_CONFLICT:
+ case REF_TRANSACTION_ERROR_NAME_CONFLICT:
ret = STORE_REF_ERROR_DF_CONFLICT;
goto out;
default:
@@ -911,7 +910,8 @@ static int update_local_ref(struct ref *ref,
struct commit *current = NULL, *updated;
int fast_forward = 0;
- if (!repo_has_object_file(the_repository, &ref->new_oid))
+ if (!has_object(the_repository, &ref->new_oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
die(_("object %s not found"), oid_to_hex(&ref->new_oid));
if (oideq(&ref->old_oid, &ref->new_oid)) {
@@ -1330,8 +1330,7 @@ static int check_exist_and_connected(struct ref *ref_map)
* we need all direct targets to exist.
*/
for (r = rm; r; r = r->next) {
- if (!repo_has_object_file_with_flags(the_repository, &r->old_oid,
- OBJECT_INFO_SKIP_FETCH_OBJECT))
+ if (!has_object(the_repository, &r->old_oid, HAS_OBJECT_RECHECK_PACKED))
return -1;
}
@@ -1638,14 +1637,11 @@ static int set_head(const struct ref *remote_refs, struct remote *remote)
get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
- fetch_map, 1);
+ fetch_map, REMOTE_GUESS_HEAD_ALL);
for (ref = matches; ref; ref = ref->next) {
string_list_append(&heads, strip_refshead(ref->name));
}
- if (follow_remote_head == FOLLOW_REMOTE_NEVER)
- goto cleanup;
-
if (!heads.nr)
result = 1;
else if (heads.nr > 1)
@@ -1691,21 +1687,6 @@ cleanup:
return result;
}
-static int uses_remote_tracking(struct transport *transport, struct refspec *rs)
-{
- if (!remote_is_configured(transport->remote, 0))
- return 0;
-
- if (!rs->nr)
- rs = &transport->remote->fetch;
-
- for (int i = 0; i < rs->nr; i++)
- if (rs->items[i].dst)
- return 1;
-
- return 0;
-}
-
static int do_fetch(struct transport *transport,
struct refspec *rs,
const struct fetch_config *config)
@@ -1718,9 +1699,9 @@ 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;
+ int do_set_head = 0;
if (tags == TAGS_DEFAULT) {
if (transport->remote->fetch_tags == 2)
@@ -1737,28 +1718,17 @@ 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);
- if (transport->remote->fetch.nr)
+ if (transport->remote->fetch.nr) {
refspec_ref_prefixes(&transport->remote->fetch,
&transport_ls_refs_options.ref_prefixes);
- if (branch_has_merge_config(branch) &&
+ if (transport->remote->follow_remote_head != FOLLOW_REMOTE_NEVER)
+ do_set_head = 1;
+ }
+ if (branch && branch_has_merge_config(branch) &&
!strcmp(branch->remote_name, transport->remote->name)) {
int i;
for (i = 0; i < branch->merge_nr; i++) {
@@ -1766,23 +1736,29 @@ 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)
- strvec_push(&transport_ls_refs_options.ref_prefixes,
- "refs/tags/");
- }
-
- if (uses_remote_tracking(transport, rs)) {
- 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,
"HEAD");
}
- if (must_list_refs) {
+ if (tags == TAGS_SET || tags == TAGS_DEFAULT)
+ strvec_push(&transport_ls_refs_options.ref_prefixes,
+ "refs/tags/");
+
+ if (do_set_head)
+ 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);
@@ -1867,8 +1843,15 @@ static int do_fetch(struct transport *transport,
goto cleanup;
retcode = ref_transaction_commit(transaction, &err);
- if (retcode)
+ if (retcode) {
+ /*
+ * Explicitly handle transaction cleanup to avoid
+ * aborting an already closed transaction.
+ */
+ ref_transaction_free(transaction);
+ transaction = NULL;
goto cleanup;
+ }
}
commit_fetch_head(&fetch_head);
@@ -1926,12 +1909,13 @@ 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))
- ;
+ if (do_set_head) {
/*
- * Way too many cases where this can go wrong
- * so let's just fail silently for now.
+ * Way too many cases where this can go wrong so let's just
+ * ignore errors and fail silently for now.
*/
+ set_head(remote_refs, transport->remote);
+ }
cleanup:
if (retcode) {
@@ -2367,8 +2351,14 @@ int cmd_fetch(int argc,
OPT_SET_INT_F(0, "refetch", &refetch,
N_("re-fetch without negotiating common commits"),
1, PARSE_OPT_NONEG),
- { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
- N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
+ {
+ .type = OPTION_STRING,
+ .long_name = "submodule-prefix",
+ .value = &submodule_prefix,
+ .argh = N_("dir"),
+ .help = N_("prepend this to submodule path output"),
+ .flags = PARSE_OPT_HIDDEN,
+ },
OPT_CALLBACK_F(0, "recurse-submodules-default",
&recurse_submodules_default, N_("on-demand"),
N_("default for recursive fetching of submodules "
@@ -2570,6 +2560,7 @@ int cmd_fetch(int argc,
if (server_options.nr)
gtransport->server_options = &server_options;
result = transport_fetch_refs(gtransport, NULL);
+ gtransport->smart_options->acked_commits = NULL;
oidset_iter_init(&acked_commits, &iter);
while ((oid = oidset_iter_next(&iter)))
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 189cd1096a..3b6aac2cf7 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -20,13 +20,26 @@ int cmd_fmt_merge_msg(int argc,
char *into_name = NULL;
int shortlog_len = -1;
struct option options[] = {
- { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
- N_("populate log with at most <n> entries from shortlog"),
- PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
- { OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"),
- N_("alias for --log (deprecated)"),
- PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL,
- DEFAULT_MERGE_LOG_LEN },
+ {
+ .type = OPTION_INTEGER,
+ .long_name = "log",
+ .value = &shortlog_len,
+ .precision = sizeof(shortlog_len),
+ .argh = N_("n"),
+ .help = N_("populate log with at most <n> entries from shortlog"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = DEFAULT_MERGE_LOG_LEN,
+ },
+ {
+ .type = OPTION_INTEGER,
+ .long_name = "summary",
+ .value = &shortlog_len,
+ .precision = sizeof(shortlog_len),
+ .argh = N_("n"),
+ .help = N_("alias for --log (deprecated)"),
+ .flags = PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN,
+ .defval = DEFAULT_MERGE_LOG_LEN,
+ },
OPT_STRING('m', "message", &message, N_("text"),
N_("use <text> as start of message")),
OPT_STRING(0, "into-name", &into_name, N_("name"),
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 8085ebd8fe..3d2207ec77 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "commit.h"
#include "config.h"
@@ -20,7 +19,7 @@ static char const * const for_each_ref_usage[] = {
int cmd_for_each_ref(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
struct ref_sorting *sorting;
struct string_list sorting_options = STRING_LIST_INIT_DUP;
@@ -63,7 +62,7 @@ int cmd_for_each_ref(int argc,
format.format = "%(objectname) %(objecttype)\t%(refname)";
- git_config(git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
/* Set default (refname) sorting */
string_list_append(&sorting_options, "refname");
diff --git a/builtin/fsck.c b/builtin/fsck.c
index eea1d43647..e7d96a9c8e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -17,7 +17,7 @@
#include "packfile.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "path.h"
#include "read-cache-ll.h"
#include "replace-object.h"
@@ -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
@@ -331,7 +332,7 @@ static void check_unreachable_object(struct object *obj)
describe_object(&obj->oid));
FILE *f;
- if (safe_create_leading_directories_const(filename)) {
+ if (safe_create_leading_directories_const(the_repository, filename)) {
error(_("could not create lost-found"));
free(filename);
return;
@@ -399,12 +400,12 @@ static void check_connectivity(void)
}
/* Look up all the requirements, warn about missing objects.. */
- max = get_max_object_index();
+ max = get_max_object_index(the_repository);
if (verbose)
fprintf_ln(stderr, _("Checking connectivity (%d objects)"), max);
for (i = 0; i < max; i++) {
- struct object *obj = get_indexed_object(i);
+ struct object *obj = get_indexed_object(the_repository, i);
if (obj)
check_object(obj);
@@ -613,23 +614,20 @@ static void get_default_heads(void)
struct for_each_loose_cb
{
struct progress *progress;
- struct strbuf obj_type;
};
-static int fsck_loose(const struct object_id *oid, const char *path, void *data)
+static int fsck_loose(const struct object_id *oid, const char *path,
+ void *data UNUSED)
{
- struct for_each_loose_cb *cb_data = data;
struct object *obj;
enum object_type type = OBJ_NONE;
unsigned long size;
void *contents = NULL;
int eaten;
struct object_info oi = OBJECT_INFO_INIT;
- struct object_id real_oid = *null_oid();
+ struct object_id real_oid = *null_oid(the_hash_algo);
int err = 0;
- strbuf_reset(&cb_data->obj_type);
- oi.type_name = &cb_data->obj_type;
oi.sizep = &size;
oi.typep = &type;
@@ -641,10 +639,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
err = error(_("%s: object corrupt or missing: %s"),
oid_to_hex(oid), path);
}
- if (type != OBJ_NONE && type < 0)
- err = error(_("%s: object is of unknown type '%s': %s"),
- oid_to_hex(&real_oid), cb_data->obj_type.buf,
- path);
if (err < 0) {
errors_found |= ERROR_OBJECT;
free(contents);
@@ -696,7 +690,6 @@ static void fsck_object_dir(const char *path)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
- .obj_type = STRBUF_INIT,
.progress = progress,
};
@@ -711,7 +704,6 @@ static void fsck_object_dir(const char *path)
&cb_data);
display_progress(progress, 256);
stop_progress(&progress);
- strbuf_release(&cb_data.obj_type);
}
static int fsck_head_link(const char *head_ref_name,
@@ -905,11 +897,37 @@ static int check_pack_rev_indexes(struct repository *r, int show_progress)
return res;
}
+static void fsck_refs(struct repository *r)
+{
+ struct child_process refs_verify = CHILD_PROCESS_INIT;
+ struct progress *progress = NULL;
+
+ if (show_progress)
+ progress = start_progress(r, _("Checking ref database"), 1);
+
+ if (verbose)
+ fprintf_ln(stderr, _("Checking ref database"));
+
+ child_process_init(&refs_verify);
+ refs_verify.git_cmd = 1;
+ strvec_pushl(&refs_verify.args, "refs", "verify", NULL);
+ if (verbose)
+ strvec_push(&refs_verify.args, "--verbose");
+ if (check_strict)
+ strvec_push(&refs_verify.args, "--strict");
+
+ if (run_command(&refs_verify))
+ errors_found |= ERROR_REFS;
+
+ display_progress(progress, 1);
+ stop_progress(&progress);
+}
+
static char const * const fsck_usage[] = {
N_("git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n"
- " [--[no-]name-objects] [<object>...]"),
+ " [--[no-]name-objects] [--[no-]references] [<object>...]"),
NULL
};
@@ -928,6 +946,7 @@ static struct option fsck_opts[] = {
N_("write dangling objects in .git/lost-found")),
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
OPT_BOOL(0, "name-objects", &name_objects, N_("show verbose names for reachable objects")),
+ OPT_BOOL(0, "references", &check_references, N_("check reference database consistency")),
OPT_END(),
};
@@ -970,6 +989,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,
diff --git a/builtin/gc.c b/builtin/gc.c
index 99431fd467..7dc94f243d 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -16,6 +16,7 @@
#include "builtin.h"
#include "abspath.h"
#include "date.h"
+#include "dir.h"
#include "environment.h"
#include "hex.h"
#include "config.h"
@@ -29,10 +30,11 @@
#include "commit-graph.h"
#include "packfile.h"
#include "object-file.h"
-#include "object-store-ll.h"
#include "pack.h"
#include "pack-objects.h"
#include "path.h"
+#include "reflog.h"
+#include "rerere.h"
#include "blob.h"
#include "tree.h"
#include "promisor-remote.h"
@@ -43,6 +45,7 @@
#include "hook.h"
#include "setup.h"
#include "trace2.h"
+#include "worktree.h"
#define FAILED_RUN "failed to run %s"
@@ -52,16 +55,9 @@ static const char * const builtin_gc_usage[] = {
};
static timestamp_t gc_log_expire_time;
-
-static struct strvec reflog = STRVEC_INIT;
static struct strvec repack = STRVEC_INIT;
-static struct strvec prune = STRVEC_INIT;
-static struct strvec prune_worktrees = STRVEC_INIT;
-static struct strvec rerere = STRVEC_INIT;
-
static struct tempfile *pidfile;
static struct lock_file log_lock;
-
static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
static void clean_pack_garbage(void)
@@ -288,6 +284,146 @@ static int maintenance_task_pack_refs(struct maintenance_run_opts *opts,
return run_command(&cmd);
}
+struct count_reflog_entries_data {
+ struct expire_reflog_policy_cb policy;
+ size_t count;
+ size_t limit;
+};
+
+static int count_reflog_entries(struct object_id *old_oid, struct object_id *new_oid,
+ const char *committer, timestamp_t timestamp,
+ int tz, const char *msg, void *cb_data)
+{
+ struct count_reflog_entries_data *data = cb_data;
+ if (should_expire_reflog_ent(old_oid, new_oid, committer, timestamp, tz, msg, &data->policy))
+ data->count++;
+ return data->count >= data->limit;
+}
+
+static int reflog_expire_condition(struct gc_config *cfg UNUSED)
+{
+ timestamp_t now = time(NULL);
+ struct count_reflog_entries_data data = {
+ .policy = {
+ .opts = REFLOG_EXPIRE_OPTIONS_INIT(now),
+ },
+ };
+ int limit = 100;
+
+ git_config_get_int("maintenance.reflog-expire.auto", &limit);
+ if (!limit)
+ return 0;
+ if (limit < 0)
+ return 1;
+ data.limit = limit;
+
+ repo_config(the_repository, reflog_expire_config, &data.policy.opts);
+
+ reflog_expire_options_set_refname(&data.policy.opts, "HEAD");
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository), "HEAD",
+ count_reflog_entries, &data);
+
+ reflog_expiry_cleanup(&data.policy);
+ return data.count >= data.limit;
+}
+
+static int maintenance_task_reflog_expire(struct maintenance_run_opts *opts UNUSED,
+ struct gc_config *cfg UNUSED)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ cmd.git_cmd = 1;
+ strvec_pushl(&cmd.args, "reflog", "expire", "--all", NULL);
+ return run_command(&cmd);
+}
+
+static int maintenance_task_worktree_prune(struct maintenance_run_opts *opts UNUSED,
+ struct gc_config *cfg)
+{
+ struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
+
+ prune_worktrees_cmd.git_cmd = 1;
+ strvec_pushl(&prune_worktrees_cmd.args, "worktree", "prune", "--expire", NULL);
+ strvec_push(&prune_worktrees_cmd.args, cfg->prune_worktrees_expire);
+
+ return run_command(&prune_worktrees_cmd);
+}
+
+static int worktree_prune_condition(struct gc_config *cfg)
+{
+ struct strbuf buf = STRBUF_INIT;
+ int should_prune = 0, limit = 1;
+ timestamp_t expiry_date;
+ struct dirent *d;
+ DIR *dir = NULL;
+
+ git_config_get_int("maintenance.worktree-prune.auto", &limit);
+ if (limit <= 0) {
+ should_prune = limit < 0;
+ goto out;
+ }
+
+ if (parse_expiry_date(cfg->prune_worktrees_expire, &expiry_date))
+ goto out;
+
+ dir = opendir(repo_git_path_replace(the_repository, &buf, "worktrees"));
+ if (!dir)
+ goto out;
+
+ while (limit && (d = readdir_skip_dot_and_dotdot(dir))) {
+ char *wtpath;
+ strbuf_reset(&buf);
+ if (should_prune_worktree(d->d_name, &buf, &wtpath, expiry_date))
+ limit--;
+ free(wtpath);
+ }
+
+ should_prune = !limit;
+
+out:
+ if (dir)
+ closedir(dir);
+ strbuf_release(&buf);
+ return should_prune;
+}
+
+static int maintenance_task_rerere_gc(struct maintenance_run_opts *opts UNUSED,
+ struct gc_config *cfg UNUSED)
+{
+ struct child_process rerere_cmd = CHILD_PROCESS_INIT;
+ rerere_cmd.git_cmd = 1;
+ strvec_pushl(&rerere_cmd.args, "rerere", "gc", NULL);
+ return run_command(&rerere_cmd);
+}
+
+static int rerere_gc_condition(struct gc_config *cfg UNUSED)
+{
+ struct strbuf path = STRBUF_INIT;
+ int should_gc = 0, limit = 1;
+ DIR *dir = NULL;
+
+ git_config_get_int("maintenance.rerere-gc.auto", &limit);
+ if (limit <= 0) {
+ should_gc = limit < 0;
+ goto out;
+ }
+
+ /*
+ * We skip garbage collection in case we either have no "rr-cache"
+ * directory or when it doesn't contain at least one entry.
+ */
+ repo_git_path_replace(the_repository, &path, "rr-cache");
+ dir = opendir(path.buf);
+ if (!dir)
+ goto out;
+ should_gc = !!readdir_skip_dot_and_dotdot(dir);
+
+out:
+ strbuf_release(&path);
+ if (dir)
+ closedir(dir);
+ return should_gc;
+}
+
static int too_many_loose_objects(struct gc_config *cfg)
{
/*
@@ -373,9 +509,14 @@ static uint64_t total_ram(void)
#if defined(HAVE_SYSINFO)
struct sysinfo si;
- if (!sysinfo(&si))
- return si.totalram;
-#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM))
+ if (!sysinfo(&si)) {
+ uint64_t total = si.totalram;
+
+ if (si.mem_unit > 1)
+ total *= (uint64_t)si.mem_unit;
+ return total;
+ }
+#elif defined(HAVE_BSD_SYSCTL) && (defined(HW_MEMSIZE) || defined(HW_PHYSMEM) || defined(HW_PHYSMEM64))
int64_t physical_memory;
int mib[2];
size_t length;
@@ -383,6 +524,8 @@ static uint64_t total_ram(void)
mib[0] = CTL_HW;
# if defined(HW_MEMSIZE)
mib[1] = HW_MEMSIZE;
+# elif defined(HW_PHYSMEM64)
+ mib[1] = HW_PHYSMEM64;
# else
mib[1] = HW_PHYSMEM;
# endif
@@ -667,21 +810,14 @@ static void gc_before_repack(struct maintenance_run_opts *opts,
if (cfg->pack_refs && maintenance_task_pack_refs(opts, cfg))
die(FAILED_RUN, "pack-refs");
-
- if (cfg->prune_reflogs) {
- struct child_process cmd = CHILD_PROCESS_INIT;
-
- cmd.git_cmd = 1;
- strvec_pushv(&cmd.args, reflog.v);
- if (run_command(&cmd))
- die(FAILED_RUN, reflog.v[0]);
- }
+ if (cfg->prune_reflogs && maintenance_task_reflog_expire(opts, cfg))
+ die(FAILED_RUN, "reflog");
}
int cmd_gc(int argc,
-const char **argv,
-const char *prefix,
-struct repository *repo UNUSED)
+ const char **argv,
+ const char *prefix,
+ struct repository *repo UNUSED)
{
int aggressive = 0;
int quiet = 0;
@@ -691,7 +827,6 @@ struct repository *repo UNUSED)
int daemonized = 0;
int keep_largest_pack = -1;
timestamp_t dummy;
- struct child_process rerere_cmd = CHILD_PROCESS_INIT;
struct maintenance_run_opts opts = MAINTENANCE_RUN_OPTS_INIT;
struct gc_config cfg = GC_CONFIG_INIT;
const char *prune_expire_sentinel = "sentinel";
@@ -699,12 +834,18 @@ struct repository *repo UNUSED)
int ret;
struct option builtin_gc_options[] = {
OPT__QUIET(&quiet, N_("suppress progress reporting")),
- { OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"),
- N_("prune unreferenced objects"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg },
+ {
+ .type = OPTION_STRING,
+ .long_name = "prune",
+ .value = &prune_expire_arg,
+ .argh = N_("date"),
+ .help = N_("prune unreferenced objects"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (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_UNSIGNED(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),
@@ -723,11 +864,7 @@ struct repository *repo UNUSED)
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);
- strvec_pushl(&prune, "prune", "--expire", NULL);
- strvec_pushl(&prune_worktrees, "worktree", "prune", "--expire", NULL);
- strvec_pushl(&rerere, "rerere", "gc", NULL);
gc_config(&cfg);
@@ -853,34 +990,27 @@ struct repository *repo UNUSED)
if (cfg.prune_expire) {
struct child_process prune_cmd = CHILD_PROCESS_INIT;
+ strvec_pushl(&prune_cmd.args, "prune", "--expire", NULL);
/* run `git prune` even if using cruft packs */
- strvec_push(&prune, cfg.prune_expire);
+ strvec_push(&prune_cmd.args, cfg.prune_expire);
if (quiet)
- strvec_push(&prune, "--no-progress");
+ strvec_push(&prune_cmd.args, "--no-progress");
if (repo_has_promisor_remote(the_repository))
- strvec_push(&prune,
+ strvec_push(&prune_cmd.args,
"--exclude-promisor-objects");
prune_cmd.git_cmd = 1;
- strvec_pushv(&prune_cmd.args, prune.v);
+
if (run_command(&prune_cmd))
- die(FAILED_RUN, prune.v[0]);
+ die(FAILED_RUN, prune_cmd.args.v[0]);
}
}
- if (cfg.prune_worktrees_expire) {
- struct child_process prune_worktrees_cmd = CHILD_PROCESS_INIT;
+ if (cfg.prune_worktrees_expire &&
+ maintenance_task_worktree_prune(&opts, &cfg))
+ die(FAILED_RUN, "worktree");
- 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))
- die(FAILED_RUN, prune_worktrees.v[0]);
- }
-
- rerere_cmd.git_cmd = 1;
- strvec_pushv(&rerere_cmd.args, rerere.v);
- if (run_command(&rerere_cmd))
- die(FAILED_RUN, rerere.v[0]);
+ if (maintenance_task_rerere_gc(&opts, &cfg))
+ die(FAILED_RUN, "rerere");
report_garbage = report_pack_garbage;
reprepare_packed_git(the_repository);
@@ -1029,6 +1159,8 @@ static int run_write_commit_graph(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
return !!run_command(&child);
}
@@ -1161,6 +1293,7 @@ static int write_loose_object_to_stdin(const struct object_id *oid,
fprintf(d->in, "%s\n", oid_to_hex(oid));
+ /* If batch_size is INT_MAX, then this will return 0 always. */
return ++(d->count) > d->batch_size;
}
@@ -1185,6 +1318,8 @@ static int pack_loose(struct maintenance_run_opts *opts)
strvec_push(&pack_proc.args, "pack-objects");
if (opts->quiet)
strvec_push(&pack_proc.args, "--quiet");
+ else
+ strvec_push(&pack_proc.args, "--no-quiet");
strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->odb->path);
pack_proc.in = -1;
@@ -1204,6 +1339,15 @@ static int pack_loose(struct maintenance_run_opts *opts)
data.count = 0;
data.batch_size = 50000;
+ repo_config_get_int(r, "maintenance.loose-objects.batchSize",
+ &data.batch_size);
+
+ /* If configured as 0, then remove limit. */
+ if (!data.batch_size)
+ data.batch_size = INT_MAX;
+ else if (data.batch_size > 0)
+ data.batch_size--; /* Decrease for equality on limit. */
+
for_each_loose_file_in_objdir(r->objects->odb->path,
write_loose_object_to_stdin,
NULL,
@@ -1263,6 +1407,8 @@ static int multi_pack_index_write(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
if (run_command(&child))
return error(_("failed to write multi-pack-index"));
@@ -1279,6 +1425,8 @@ static int multi_pack_index_expire(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
if (run_command(&child))
return error(_("'git multi-pack-index expire' failed"));
@@ -1335,6 +1483,8 @@ static int multi_pack_index_repack(struct maintenance_run_opts *opts)
if (opts->quiet)
strvec_push(&child.args, "--no-progress");
+ else
+ strvec_push(&child.args, "--progress");
strvec_pushf(&child.args, "--batch-size=%"PRIuMAX,
(uintmax_t)get_auto_pack_size());
@@ -1392,6 +1542,9 @@ enum maintenance_task_label {
TASK_GC,
TASK_COMMIT_GRAPH,
TASK_PACK_REFS,
+ TASK_REFLOG_EXPIRE,
+ TASK_WORKTREE_PRUNE,
+ TASK_RERERE_GC,
/* Leave as final value */
TASK__COUNT
@@ -1428,6 +1581,21 @@ static struct maintenance_task tasks[] = {
maintenance_task_pack_refs,
pack_refs_condition,
},
+ [TASK_REFLOG_EXPIRE] = {
+ "reflog-expire",
+ maintenance_task_reflog_expire,
+ reflog_expire_condition,
+ },
+ [TASK_WORKTREE_PRUNE] = {
+ "worktree-prune",
+ maintenance_task_worktree_prune,
+ worktree_prune_condition,
+ },
+ [TASK_RERERE_GC] = {
+ "rerere-gc",
+ maintenance_task_rerere_gc,
+ rerere_gc_condition,
+ },
};
static int compare_tasks_by_selection(const void *a_, const void *b_)
@@ -2075,7 +2243,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
case SCHEDULE_DAILY:
repeat = "<dict>\n"
- "<key>Day</key><integer>%d</integer>\n"
+ "<key>Weekday</key><integer>%d</integer>\n"
"<key>Hour</key><integer>0</integer>\n"
"<key>Minute</key><integer>%d</integer>\n"
"</dict>\n";
@@ -2086,7 +2254,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
case SCHEDULE_WEEKLY:
strbuf_addf(&plist,
"<dict>\n"
- "<key>Day</key><integer>0</integer>\n"
+ "<key>Weekday</key><integer>0</integer>\n"
"<key>Hour</key><integer>0</integer>\n"
"<key>Minute</key><integer>%d</integer>\n"
"</dict>\n",
@@ -2099,7 +2267,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
}
strbuf_addstr(&plist, "</array>\n</dict>\n</plist>\n");
- if (safe_create_leading_directories(filename))
+ if (safe_create_leading_directories(the_repository, filename))
die(_("failed to create directories for '%s'"), filename);
if ((long)lock_file_timeout_ms < 0 &&
@@ -2565,7 +2733,7 @@ static int systemd_timer_write_timer_file(enum schedule_priority schedule,
filename = xdg_config_home_systemd(local_timer_name);
- if (safe_create_leading_directories(filename)) {
+ if (safe_create_leading_directories(the_repository, filename)) {
error(_("failed to create directories for '%s'"), filename);
goto error;
}
@@ -2638,7 +2806,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
char *local_service_name = xstrfmt(SYSTEMD_UNIT_FORMAT, "", "service");
filename = xdg_config_home_systemd(local_service_name);
- if (safe_create_leading_directories(filename)) {
+ if (safe_create_leading_directories(the_repository, filename)) {
error(_("failed to create directories for '%s'"), filename);
goto error;
}
diff --git a/builtin/grep.c b/builtin/grep.c
index d1427290f7..3ce574a605 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -26,7 +26,7 @@
#include "submodule-config.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "packfile.h"
#include "pager.h"
#include "path.h"
@@ -453,7 +453,7 @@ static int grep_submodule(struct grep_opt *opt,
return 0;
subrepo = xmalloc(sizeof(*subrepo));
- if (repo_submodule_init(subrepo, superproject, path, null_oid())) {
+ if (repo_submodule_init(subrepo, superproject, path, null_oid(opt->repo->hash_algo))) {
free(subrepo);
return 0;
}
@@ -983,9 +983,9 @@ int cmd_grep(int argc,
OPT_CALLBACK('C', "context", &opt, N_("n"),
N_("show <n> context lines before and after matches"),
context_callback),
- OPT_INTEGER('B', "before-context", &opt.pre_context,
+ OPT_UNSIGNED('B', "before-context", &opt.pre_context,
N_("show <n> context lines before matches")),
- OPT_INTEGER('A', "after-context", &opt.post_context,
+ OPT_UNSIGNED('A', "after-context", &opt.post_context,
N_("show <n> context lines after matches")),
OPT_INTEGER(0, "threads", &num_threads,
N_("use <n> worker threads")),
@@ -1017,10 +1017,16 @@ int cmd_grep(int argc,
OPT_BOOL(0, "all-match", &opt.all_match,
N_("show only matches from files that match all patterns")),
OPT_GROUP(""),
- { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
- N_("pager"), N_("show matching files in the pager"),
- PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
- NULL, (intptr_t)default_pager },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'O',
+ .long_name = "open-files-in-pager",
+ .value = &show_in_pager,
+ .argh = N_("pager"),
+ .help = N_("show matching files in the pager"),
+ .flags = PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
+ .defval = (intptr_t)default_pager,
+ },
OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
N_("allow calling of grep(1) (ignored by this build)"),
PARSE_OPT_NOCOMPLETE),
@@ -1144,7 +1150,7 @@ int cmd_grep(int argc,
break;
}
- object = parse_object_or_die(&oid, arg);
+ object = parse_object_or_die(the_repository, &oid, arg);
if (!seen_dashdash)
verify_non_filename(prefix, arg);
add_object_array_with_path(object, arg, &list, oc.mode, oc.path);
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index a25f0403f4..6a99ec250d 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -11,7 +11,7 @@
#include "gettext.h"
#include "hex.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "blob.h"
#include "quote.h"
#include "parse-options.h"
@@ -19,38 +19,15 @@
#include "strbuf.h"
#include "write-or-die.h"
-/*
- * This is to create corrupt objects for debugging and as such it
- * needs to bypass the data conversion performed by, and the type
- * limitation imposed by, index_fd() and its callees.
- */
-static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags)
-{
- struct strbuf buf = STRBUF_INIT;
- int ret;
-
- if (strbuf_read(&buf, fd, 4096) < 0)
- ret = -1;
- else
- ret = write_object_file_literally(buf.buf, buf.len, type, oid,
- flags);
- close(fd);
- strbuf_release(&buf);
- return ret;
-}
-
-static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
- int literally)
+static void hash_fd(int fd, const char *type, const char *path, unsigned flags)
{
struct stat st;
struct object_id oid;
if (fstat(fd, &st) < 0 ||
- (literally
- ? hash_literally(&oid, fd, type, flags)
- : index_fd(the_repository->index, &oid, fd, &st,
- type_from_string(type), path, flags)))
- die((flags & HASH_WRITE_OBJECT)
+ index_fd(the_repository->index, &oid, fd, &st,
+ type_from_string(type), path, flags))
+ die((flags & INDEX_WRITE_OBJECT)
? "Unable to add %s to database"
: "Unable to hash %s", path);
printf("%s\n", oid_to_hex(&oid));
@@ -58,15 +35,14 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
}
static void hash_object(const char *path, const char *type, const char *vpath,
- unsigned flags, int literally)
+ unsigned flags)
{
int fd;
fd = xopen(path, O_RDONLY);
- hash_fd(fd, type, vpath, flags, literally);
+ hash_fd(fd, type, vpath, flags);
}
-static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
- int literally)
+static void hash_stdin_paths(const char *type, int no_filters, unsigned flags)
{
struct strbuf buf = STRBUF_INIT;
struct strbuf unquoted = STRBUF_INIT;
@@ -78,8 +54,7 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
die("line is badly quoted");
strbuf_swap(&buf, &unquoted);
}
- hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags,
- literally);
+ hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags);
}
strbuf_release(&buf);
strbuf_release(&unquoted);
@@ -100,19 +75,20 @@ int cmd_hash_object(int argc,
int hashstdin = 0;
int stdin_paths = 0;
int no_filters = 0;
- int literally = 0;
int nongit = 0;
- unsigned flags = HASH_FORMAT_CHECK;
+ unsigned flags = INDEX_FORMAT_CHECK;
const char *vpath = NULL;
char *vpath_free = NULL;
const struct option hash_object_options[] = {
OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
OPT_BIT('w', NULL, &flags, N_("write the object into the object database"),
- HASH_WRITE_OBJECT),
+ INDEX_WRITE_OBJECT),
OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
- OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")),
+ OPT_NEGBIT( 0, "literally", &flags,
+ N_("just hash any random garbage to create corrupt objects for debugging Git"),
+ INDEX_FORMAT_CHECK),
OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
OPT_END()
};
@@ -122,7 +98,7 @@ int cmd_hash_object(int argc,
argc = parse_options(argc, argv, prefix, hash_object_options,
hash_object_usage, 0);
- if (flags & HASH_WRITE_OBJECT)
+ if (flags & INDEX_WRITE_OBJECT)
prefix = setup_git_directory();
else
prefix = setup_git_directory_gently(&nongit);
@@ -158,7 +134,7 @@ int cmd_hash_object(int argc,
}
if (hashstdin)
- hash_fd(0, type, vpath, flags, literally);
+ hash_fd(0, type, vpath, flags);
for (i = 0 ; i < argc; i++) {
const char *arg = argv[i];
@@ -167,12 +143,12 @@ int cmd_hash_object(int argc,
if (prefix)
arg = to_free = prefix_filename(prefix, arg);
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
- flags, literally);
+ flags);
free(to_free);
}
if (stdin_paths)
- hash_stdin_paths(type, no_filters, flags, literally);
+ hash_stdin_paths(type, no_filters, flags);
free(vpath_free);
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 52cc97d52c..bb7925bd29 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -21,7 +21,7 @@
#include "packfile.h"
#include "pack-revindex.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "oid-array.h"
#include "oidset.h"
#include "path.h"
@@ -279,14 +279,14 @@ static unsigned check_objects(void)
{
unsigned i, max, foreign_nr = 0;
- max = get_max_object_index();
+ max = get_max_object_index(the_repository);
if (verbose)
progress = start_delayed_progress(the_repository,
_("Checking objects"), max);
for (i = 0; i < max; i++) {
- foreign_nr += check_object(get_indexed_object(i));
+ foreign_nr += check_object(get_indexed_object(the_repository, i));
display_progress(progress, i + 1);
}
@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
git_hash_update(&c, hdr, hdrlen);
} else
oid = NULL;
- if (type == OBJ_BLOB && size > big_file_threshold)
+ if (type == OBJ_BLOB &&
+ size > repo_settings_get_big_file_threshold(the_repository))
buf = fixed_buf;
else
buf = xmallocz(size);
@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)
enum object_type type;
unsigned long size;
- if (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)
+ if (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||
+ entry->type != OBJ_BLOB)
return -1;
memset(&data, 0, sizeof(data));
@@ -890,9 +892,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
if (startup_info->have_repository) {
read_lock();
- collision_test_needed =
- repo_has_object_file_with_flags(the_repository, oid,
- OBJECT_INFO_QUICK);
+ collision_test_needed = has_object(the_repository, oid,
+ HAS_OBJECT_FETCH_PROMISOR);
read_unlock();
}
@@ -1107,8 +1108,8 @@ static void *threaded_second_pass(void *data)
set_thread_data(data);
for (;;) {
struct base_data *parent = NULL;
- struct object_entry *child_obj;
- struct base_data *child;
+ struct object_entry *child_obj = NULL;
+ struct base_data *child = NULL;
counter_lock();
display_progress(progress, nr_resolved_deltas);
@@ -1135,15 +1136,18 @@ static void *threaded_second_pass(void *data)
parent = list_first_entry(&work_head, struct base_data,
list);
- if (parent->ref_first <= parent->ref_last) {
+ while (parent->ref_first <= parent->ref_last) {
int offset = ref_deltas[parent->ref_first++].obj_no;
child_obj = objects + offset;
- if (child_obj->real_type != OBJ_REF_DELTA)
- die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)",
- (uintmax_t) child_obj->idx.offset,
- oid_to_hex(&parent->obj->idx.oid));
+ if (child_obj->real_type != OBJ_REF_DELTA) {
+ child_obj = NULL;
+ continue;
+ }
child_obj->real_type = parent->obj->real_type;
- } else {
+ break;
+ }
+
+ if (!child_obj && parent->ofs_first <= parent->ofs_last) {
child_obj = objects +
ofs_deltas[parent->ofs_first++].obj_no;
assert(child_obj->real_type == OBJ_OFS_DELTA);
@@ -1176,29 +1180,32 @@ static void *threaded_second_pass(void *data)
}
work_unlock();
- if (parent) {
- child = resolve_delta(child_obj, parent);
- if (!child->children_remaining)
- FREE_AND_NULL(child->data);
- } else {
- child = make_base(child_obj, NULL);
- if (child->children_remaining) {
- /*
- * Since this child has its own delta children,
- * we will need this data in the future.
- * Inflate now so that future iterations will
- * have access to this object's data while
- * outside the work mutex.
- */
- child->data = get_data_from_pack(child_obj);
- child->size = child_obj->size;
+ if (child_obj) {
+ if (parent) {
+ child = resolve_delta(child_obj, parent);
+ if (!child->children_remaining)
+ FREE_AND_NULL(child->data);
+ } else{
+ child = make_base(child_obj, NULL);
+ if (child->children_remaining) {
+ /*
+ * Since this child has its own delta children,
+ * we will need this data in the future.
+ * Inflate now so that future iterations will
+ * have access to this object's data while
+ * outside the work mutex.
+ */
+ child->data = get_data_from_pack(child_obj);
+ child->size = child_obj->size;
+ }
}
}
work_lock();
if (parent)
parent->retain_data--;
- if (child->data) {
+
+ if (child && child->data) {
/*
* This child has its own children, so add it to
* work_head.
@@ -1207,7 +1214,7 @@ static void *threaded_second_pass(void *data)
base_cache_used += child->size;
prune_base_data(NULL);
free_base_data(child);
- } else {
+ } else if (child) {
/*
* This child does not have its own children. It may be
* the last descendant of its ancestors; free those
@@ -1286,6 +1293,7 @@ static void parse_pack_objects(unsigned char *hash)
/* Check pack integrity */
flush();
+ the_hash_algo->init_fn(&tmp_ctx);
git_hash_clone(&tmp_ctx, &input_ctx);
git_hash_final(hash, &tmp_ctx);
if (!hasheq(fill(the_hash_algo->rawsz), hash, the_repository->hash_algo))
@@ -1381,7 +1389,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
REALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1);
memset(objects + nr_objects + 1, 0,
nr_unresolved * sizeof(*objects));
- f = hashfd(output_fd, curr_pack);
+ f = hashfd(the_repository->hash_algo, output_fd, curr_pack);
fix_unresolved_deltas(f);
strbuf_addf(&msg, Q_("completed with %d local object",
"completed with %d local objects",
@@ -1562,7 +1570,7 @@ static void write_special_file(const char *suffix, const char *msg,
else
filename = odb_pack_name(the_repository, &name_buf, hash, suffix);
- fd = odb_pack_keep(filename);
+ fd = safe_create_file_with_leading_directories(the_repository, filename);
if (fd < 0) {
if (errno != EEXIST)
die_errno(_("cannot write %s file '%s'"),
@@ -2088,10 +2096,10 @@ 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(the_hash_algo, index_name, idx_objects,
+ curr_index = write_idx_file(the_repository, index_name, idx_objects,
nr_objects, &opts, pack_hash);
if (rev_index)
- curr_rev_index = write_rev_file(the_hash_algo, rev_index_name,
+ curr_rev_index = write_rev_file(the_repository, rev_index_name,
idx_objects, nr_objects,
pack_hash, opts.flags);
free(idx_objects);
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 196dccdd77..bb853e69f5 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -8,7 +8,6 @@
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
#include "path.h"
#include "refs.h"
@@ -93,10 +92,15 @@ int cmd_init_db(int argc,
N_("directory from which templates will be used")),
OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
N_("create a bare repository"), 1),
- { OPTION_CALLBACK, 0, "shared", &init_shared_repository,
- N_("permissions"),
- N_("specify that the git repository is to be shared amongst several users"),
- PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
+ {
+ .type = OPTION_CALLBACK,
+ .long_name = "shared",
+ .value = &init_shared_repository,
+ .argh = N_("permissions"),
+ .help = N_("specify that the git repository is to be shared amongst several users"),
+ .flags = PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
+ .callback = shared_callback
+ },
OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
N_("separate git dir from working tree")),
@@ -134,7 +138,7 @@ int cmd_init_db(int argc,
*/
saved = repo_settings_get_shared_repository(the_repository);
repo_settings_set_shared_repository(the_repository, 0);
- switch (safe_create_leading_directories_const(argv[0])) {
+ switch (safe_create_leading_directories_const(the_repository, argv[0])) {
case SCLD_OK:
case SCLD_PERMS:
break;
diff --git a/builtin/log.c b/builtin/log.c
index 04a6ef97bc..b450cd3bde 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -14,9 +14,8 @@
#include "gettext.h"
#include "hex.h"
#include "refs.h"
-#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "pager.h"
#include "color.h"
#include "commit.h"
@@ -29,6 +28,7 @@
#include "tag.h"
#include "reflog-walk.h"
#include "patch-ids.h"
+#include "path.h"
#include "shortlog.h"
#include "remote.h"
#include "string-list.h"
@@ -2311,7 +2311,7 @@ int cmd_format_patch(int argc,
*/
saved = repo_settings_get_shared_repository(the_repository);
repo_settings_set_shared_repository(the_repository, 0);
- switch (safe_create_leading_directories_const(output_directory)) {
+ switch (safe_create_leading_directories_const(the_repository, output_directory)) {
case SCLD_OK:
case SCLD_EXISTS:
break;
@@ -2468,7 +2468,7 @@ int cmd_format_patch(int argc,
base = get_base_commit(&cfg, list, nr);
if (base) {
reset_revision_walk();
- clear_object_flags(UNINTERESTING);
+ clear_object_flags(the_repository, UNINTERESTING);
prepare_bases(&bases, base, list, nr);
}
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index a4431429b7..be74f0a03b 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"
@@ -234,7 +233,8 @@ static void show_submodule(struct repository *superproject,
{
struct repository subrepo;
- if (repo_submodule_init(&subrepo, superproject, path, null_oid()))
+ if (repo_submodule_init(&subrepo, superproject, path,
+ null_oid(superproject->hash_algo)))
return;
if (repo_read_index(&subrepo) < 0)
@@ -245,12 +245,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 +284,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 +349,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 +371,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 +568,7 @@ static int option_parse_exclude_standard(const struct option *opt,
int cmd_ls_files(int argc,
const char **argv,
const char *cmd_prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int require_work_tree = 0, show_tag = 0, i;
char *max_prefix;
@@ -647,15 +648,15 @@ int cmd_ls_files(int argc,
show_usage_with_options_if_asked(argc, argv,
ls_files_usage, builtin_ls_files_options);
- prepare_repo_settings(the_repository);
- the_repository->settings.command_requires_full_index = 0;
+ prepare_repo_settings(repo);
+ repo->settings.command_requires_full_index = 0;
prefix = cmd_prefix;
if (prefix)
prefix_len = strlen(prefix);
- git_config(git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
- if (repo_read_index(the_repository) < 0)
+ if (repo_read_index(repo) < 0)
die("index file corrupt");
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
@@ -724,7 +725,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 +749,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/ls-remote.c b/builtin/ls-remote.c
index 42f34e1236..01a4d4daa1 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -67,9 +67,14 @@ int cmd_ls_remote(int argc,
OPT__QUIET(&quiet, N_("do not print remote URL")),
OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"),
N_("path of git-upload-pack on the remote host")),
- { OPTION_STRING, 0, "exec", &uploadpack, N_("exec"),
- N_("path of git-upload-pack on the remote host"),
- PARSE_OPT_HIDDEN },
+ {
+ .type = OPTION_STRING,
+ .long_name = "exec",
+ .value = &uploadpack,
+ .argh = N_("exec"),
+ .help = N_("path of git-upload-pack on the remote host"),
+ .flags = PARSE_OPT_HIDDEN,
+ },
OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS),
OPT_BIT('b', "branches", &flags, N_("limit to branches"), REF_BRANCHES),
OPT_BIT_F('h', "heads", &flags,
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 8542b5d53e..8aafc30ca4 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -10,7 +10,7 @@
#include "gettext.h"
#include "hex.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "tree.h"
#include "path.h"
#include "quote.h"
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 7e315f374b..2b16b10d2c 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -5,6 +5,7 @@
#include "abspath.h"
#include "diff.h"
#include "hex.h"
+#include "object-file.h"
#include "object-name.h"
#include "object-store.h"
#include "config.h"
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index abfc060e28..03b5100cfa 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -3,7 +3,7 @@
#include "advice.h"
#include "gettext.h"
#include "hash.h"
-#include "merge-recursive.h"
+#include "merge-ort-wrappers.h"
#include "object-name.h"
static const char builtin_merge_recursive_usage[] =
@@ -89,7 +89,7 @@ int cmd_merge_recursive(int argc,
if (o.verbosity >= 3)
printf(_("Merging %s with %s\n"), o.branch1, o.branch2);
- failed = merge_recursive_generic(&o, &h1, &h2, bases_count, bases, &result);
+ failed = merge_ort_generic(&o, &h1, &h2, bases_count, bases, &result);
free(better1);
free(better2);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 3ec7127b3a..7f41665dfd 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -10,7 +10,7 @@
#include "commit-reach.h"
#include "merge-ort.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "parse-options.h"
#include "blob.h"
#include "merge-blobs.h"
@@ -490,6 +490,9 @@ static int real_merge(struct merge_tree_options *o,
if (result.clean < 0)
die(_("failure to merge"));
+ if (o->merge_options.mergeability_only)
+ goto cleanup;
+
if (show_messages == -1)
show_messages = !result.clean;
@@ -522,6 +525,8 @@ static int real_merge(struct merge_tree_options *o,
}
if (o->use_stdin)
putchar(line_termination);
+
+cleanup:
merge_finalize(&opt, &result);
clear_merge_options(&opt);
return !result.clean; /* result.clean < 0 handled above */
@@ -538,6 +543,7 @@ int cmd_merge_tree(int argc,
int original_argc;
const char *merge_base = NULL;
int ret;
+ int quiet = 0;
const char * const merge_tree_usage[] = {
N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"),
@@ -552,6 +558,10 @@ int cmd_merge_tree(int argc,
N_("do a trivial merge only"), MODE_TRIVIAL),
OPT_BOOL(0, "messages", &o.show_messages,
N_("also show informational/conflict messages")),
+ OPT_BOOL_F(0, "quiet",
+ &quiet,
+ N_("suppress all output; only exit status wanted"),
+ PARSE_OPT_NONEG),
OPT_SET_INT('z', NULL, &line_termination,
N_("separate paths with the NUL character"), '\0'),
OPT_BOOL_F(0, "name-only",
@@ -583,6 +593,14 @@ int cmd_merge_tree(int argc,
argc = parse_options(argc, argv, prefix, mt_options,
merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+ if (quiet && o.show_messages == -1)
+ o.show_messages = 0;
+ o.merge_options.mergeability_only = quiet;
+ die_for_incompatible_opt2(quiet, "--quiet", o.show_messages, "--messages");
+ die_for_incompatible_opt2(quiet, "--quiet", o.name_only, "--name-only");
+ die_for_incompatible_opt2(quiet, "--quiet", o.use_stdin, "--stdin");
+ die_for_incompatible_opt2(quiet, "--quiet", !line_termination, "-z");
+
if (xopts.nr && o.mode == MODE_TRIVIAL)
die(_("--trivial-merge is incompatible with all other options"));
for (size_t x = 0; x < xopts.nr; x++)
diff --git a/builtin/merge.c b/builtin/merge.c
index ba9faf126a..ce90e52fe4 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -39,7 +39,6 @@
#include "rerere.h"
#include "help.h"
#include "merge.h"
-#include "merge-recursive.h"
#include "merge-ort-wrappers.h"
#include "resolve-undo.h"
#include "remote.h"
@@ -171,7 +170,7 @@ static struct strategy *get_strategy(const char *name)
struct strategy *ret;
static struct cmdnames main_cmds = {0}, other_cmds = {0};
static int loaded;
- char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
+ char *default_strategy = NULL;
if (!name)
return NULL;
@@ -250,9 +249,16 @@ static struct option builtin_merge_options[] = {
OPT_BOOL(0, "stat", &show_diffstat,
N_("show a diffstat at the end of the merge")),
OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
- { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
- N_("add (at most <n>) entries from shortlog to merge commit message"),
- PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
+ {
+ .type = OPTION_INTEGER,
+ .long_name = "log",
+ .value = &shortlog_len,
+ .precision = sizeof(shortlog_len),
+ .argh = N_("n"),
+ .help = N_("add (at most <n>) entries from shortlog to merge commit message"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = DEFAULT_MERGE_LOG_LEN,
+ },
OPT_BOOL(0, "squash", &squash,
N_("create a single commit instead of doing a merge")),
OPT_BOOL(0, "commit", &option_commit,
@@ -274,9 +280,16 @@ static struct option builtin_merge_options[] = {
OPT_CALLBACK('m', "message", &merge_msg, N_("message"),
N_("merge commit message (for a non-fast-forward merge)"),
option_parse_message),
- { OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"),
- N_("read message from file"), PARSE_OPT_NONEG,
- NULL, 0, option_read_message },
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .short_name = 'F',
+ .long_name = "file",
+ .value = &merge_msg,
+ .argh = N_("path"),
+ .help = N_("read message from file"),
+ .flags = PARSE_OPT_NONEG,
+ .ll_callback = option_read_message,
+ },
OPT_STRING(0, "into-name", &into_name, N_("name"),
N_("use <name> instead of the real target")),
OPT__VERBOSITY(&verbosity),
@@ -289,8 +302,16 @@ static struct option builtin_merge_options[] = {
OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories,
N_("allow merging unrelated histories")),
OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
- { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
- N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &sign_commit,
+ .argh = N_("key-id"),
+ .help = N_("GPG sign commit"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
OPT_AUTOSTASH(&autostash),
OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
OPT_BOOL(0, "signoff", &signoff, N_("add a Signed-off-by trailer")),
@@ -750,12 +771,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
repo_hold_locked_index(the_repository, &lock,
LOCK_DIE_ON_ERROR);
- if (!strcmp(strategy, "ort"))
- clean = merge_ort_recursive(&o, head, remoteheads->item,
- reversed, &result);
- else
- clean = merge_recursive(&o, head, remoteheads->item,
- reversed, &result);
+ clean = merge_ort_recursive(&o, head, remoteheads->item,
+ reversed, &result);
free_commit_list(reversed);
strbuf_release(&o.obuf);
@@ -1316,12 +1333,6 @@ int cmd_merge(int argc,
if (branch)
skip_prefix(branch, "refs/heads/", &branch);
- if (!pull_twohead) {
- char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
- if (default_strategy && !strcmp(default_strategy, "ort"))
- pull_twohead = xstrdup("ort");
- }
-
init_diff_ui_defaults();
git_config(git_merge_config, NULL);
@@ -1522,12 +1533,6 @@ int cmd_merge(int argc,
fast_forward = FF_NO;
}
- if (!use_strategies && !pull_twohead &&
- remoteheads && !remoteheads->next) {
- char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
- if (default_strategy)
- append_strategy(get_strategy(default_strategy));
- }
if (!use_strategies) {
if (!remoteheads)
; /* already up-to-date */
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 6e188dce50..1b1dc0263e 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -6,7 +6,7 @@
#include "strbuf.h"
#include "replace-object.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "fsck.h"
#include "config.h"
@@ -41,7 +41,7 @@ static int mktag_fsck_error_func(struct fsck_options *o UNUSED,
fprintf_ln(stderr, _("error: tag input does not pass fsck: %s"), message);
return 1;
default:
- BUG(_("%d (FSCK_IGNORE?) should never trigger this callback"),
+ BUG("%d (FSCK_IGNORE?) should never trigger this callback",
msg_type);
}
}
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 3c16faa40e..4b47803467 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -11,7 +11,8 @@
#include "strbuf.h"
#include "tree.h"
#include "parse-options.h"
-#include "object-store-ll.h"
+#include "object-file.h"
+#include "object-store.h"
static struct treeent {
unsigned mode;
@@ -66,7 +67,7 @@ static void write_tree(struct object_id *oid)
strbuf_release(&buf);
}
-static const char *mktree_usage[] = {
+static const char *const mktree_usage[] = {
"git mktree [-z] [--missing] [--batch]",
NULL
};
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index 2a938466f5..69a9750732 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -7,7 +7,7 @@
#include "midx.h"
#include "strbuf.h"
#include "trace2.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "replace-object.h"
#include "repository.h"
@@ -245,7 +245,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
{
struct option *options;
static struct option builtin_multi_pack_index_repack_options[] = {
- OPT_MAGNITUDE(0, "batch-size", &opts.batch_size,
+ OPT_UNSIGNED(0, "batch-size", &opts.batch_size,
N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
OPT_BIT(0, "progress", &opts.flags,
N_("force progress reporting"), MIDX_PROGRESS),
diff --git a/builtin/mv.c b/builtin/mv.c
index 55a7d471dc..07548fe96a 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -15,6 +15,7 @@
#include "gettext.h"
#include "name-hash.h"
#include "object-file.h"
+#include "path.h"
#include "pathspec.h"
#include "lockfile.h"
#include "dir.h"
@@ -28,7 +29,8 @@
#include "entry.h"
static const char * const builtin_mv_usage[] = {
- N_("git mv [<options>] <source>... <destination>"),
+ N_("git mv [-v] [-f] [-n] [-k] <source> <destination>"),
+ N_("git mv [-v] [-f] [-n] [-k] <source>... <destination-directory>"),
NULL
};
@@ -37,6 +39,13 @@ enum update_mode {
INDEX = (1 << 2),
SPARSE = (1 << 3),
SKIP_WORKTREE_DIR = (1 << 4),
+ /*
+ * A file gets moved implicitly via a move of one of its parent
+ * directories. This flag causes us to skip the check that we don't try
+ * to move a file and any of its parent directories at the same point
+ * in time.
+ */
+ MOVE_VIA_PARENT_DIR = (1 << 5),
};
#define DUP_BASENAME 1
@@ -181,6 +190,21 @@ static void remove_empty_src_dirs(const char **src_dir, size_t src_dir_nr)
strbuf_release(&a_src_dir);
}
+struct pathmap_entry {
+ struct hashmap_entry ent;
+ const char *path;
+};
+
+static int pathmap_cmp(const void *cmp_data UNUSED,
+ const struct hashmap_entry *a,
+ const struct hashmap_entry *b,
+ const void *key UNUSED)
+{
+ const struct pathmap_entry *e1 = container_of(a, struct pathmap_entry, ent);
+ const struct pathmap_entry *e2 = container_of(b, struct pathmap_entry, ent);
+ return fspathcmp(e1->path, e2->path);
+}
+
int cmd_mv(int argc,
const char **argv,
const char *prefix,
@@ -211,6 +235,8 @@ int cmd_mv(int argc,
struct cache_entry *ce;
struct string_list only_match_skip_worktree = STRING_LIST_INIT_DUP;
struct string_list dirty_paths = STRING_LIST_INIT_DUP;
+ struct hashmap moved_dirs = HASHMAP_INIT(pathmap_cmp, NULL);
+ struct strbuf pathbuf = STRBUF_INIT;
int ret;
git_config(git_default_config, NULL);
@@ -329,6 +355,7 @@ int cmd_mv(int argc,
dir_check:
if (S_ISDIR(st.st_mode)) {
+ struct pathmap_entry *entry;
char *dst_with_slash;
size_t dst_with_slash_len;
int j, n;
@@ -346,6 +373,11 @@ dir_check:
goto act_on_entry;
}
+ entry = xmalloc(sizeof(*entry));
+ entry->path = src;
+ hashmap_entry_init(&entry->ent, fspathhash(src));
+ hashmap_add(&moved_dirs, &entry->ent);
+
/* last - first >= 1 */
modes[i] |= WORKING_DIRECTORY;
@@ -366,8 +398,7 @@ dir_check:
strvec_push(&sources, path);
strvec_push(&destinations, prefixed_path);
- memset(modes + argc + j, 0, sizeof(enum update_mode));
- modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX;
+ modes[argc + j] = MOVE_VIA_PARENT_DIR | (ce_skip_worktree(ce) ? SPARSE : INDEX);
submodule_gitfiles[argc + j] = NULL;
free(prefixed_path);
@@ -463,6 +494,32 @@ remove_entry:
}
}
+ for (i = 0; i < argc; i++) {
+ const char *slash_pos;
+
+ if (modes[i] & MOVE_VIA_PARENT_DIR)
+ continue;
+
+ strbuf_reset(&pathbuf);
+ strbuf_addstr(&pathbuf, sources.v[i]);
+
+ slash_pos = strrchr(pathbuf.buf, '/');
+ while (slash_pos > pathbuf.buf) {
+ struct pathmap_entry needle;
+
+ strbuf_setlen(&pathbuf, slash_pos - pathbuf.buf);
+
+ needle.path = pathbuf.buf;
+ hashmap_entry_init(&needle.ent, fspathhash(pathbuf.buf));
+
+ if (hashmap_get_entry(&moved_dirs, &needle, ent, NULL))
+ die(_("cannot move both '%s' and its parent directory '%s'"),
+ sources.v[i], pathbuf.buf);
+
+ slash_pos = strrchr(pathbuf.buf, '/');
+ }
+ }
+
if (only_match_skip_worktree.nr) {
advise_on_updating_sparse_paths(&only_match_skip_worktree);
if (!ignore_errors) {
@@ -505,7 +562,8 @@ remove_entry:
continue;
pos = index_name_pos(the_repository->index, src, strlen(src));
- assert(pos >= 0);
+ if (pos < 0)
+ BUG("could not find source in index: '%s'", src);
if (!(mode & SPARSE) && !lstat(src, &st))
sparse_and_dirty = ie_modified(the_repository->index,
the_repository->index->cache[pos],
@@ -555,7 +613,7 @@ remove_entry:
*/
char *dst_dup = xstrdup(dst);
string_list_append(&dirty_paths, dst);
- safe_create_leading_directories(dst_dup);
+ safe_create_leading_directories(the_repository, dst_dup);
FREE_AND_NULL(dst_dup);
rename(src, dst);
}
@@ -587,6 +645,8 @@ out:
strvec_clear(&dest_paths);
strvec_clear(&destinations);
strvec_clear(&submodule_gitfiles_to_free);
+ hashmap_clear_and_free(&moved_dirs, struct pathmap_entry, ent);
+ strbuf_release(&pathbuf);
free(submodule_gitfiles);
free(modes);
return ret;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index beac166b5c..ff199638de 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -567,7 +567,11 @@ int cmd_name_rev(int argc,
{
struct mem_pool string_pool;
struct object_array revs = OBJECT_ARRAY_INIT;
- int all = 0, annotate_stdin = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
+
+#ifndef WITH_BREAKING_CHANGES
+ int transform_stdin = 0;
+#endif
+ int all = 0, annotate_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
struct name_ref_data data = { 0, 0, STRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP };
struct option opts[] = {
OPT_BOOL(0, "name-only", &data.name_only, N_("print only ref-based names (no object names)")),
@@ -578,11 +582,13 @@ int cmd_name_rev(int argc,
N_("ignore refs matching <pattern>")),
OPT_GROUP(""),
OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
+#ifndef WITH_BREAKING_CHANGES
OPT_BOOL_F(0,
"stdin",
&transform_stdin,
N_("deprecated: use --annotate-stdin instead"),
PARSE_OPT_HIDDEN),
+#endif /* WITH_BREAKING_CHANGES */
OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
OPT_BOOL(0, "always", &always,
@@ -597,12 +603,14 @@ int cmd_name_rev(int argc,
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
+#ifndef WITH_BREAKING_CHANGES
if (transform_stdin) {
warning("--stdin is deprecated. Please use --annotate-stdin instead, "
"which is functionally equivalent.\n"
"This option will be removed in a future release.");
annotate_stdin = 1;
}
+#endif
if (all + annotate_stdin + !!argc > 1) {
error("Specify either a list, or --all, not both!");
@@ -667,9 +675,9 @@ int cmd_name_rev(int argc,
} else if (all) {
int i, max;
- max = get_max_object_index();
+ max = get_max_object_index(the_repository);
for (i = 0; i < max; i++) {
- struct object *obj = get_indexed_object(i);
+ struct object *obj = get_indexed_object(the_repository, i);
if (!obj || obj->type != OBJ_COMMIT)
continue;
show_name(obj, NULL,
diff --git a/builtin/notes.c b/builtin/notes.c
index ff61ec5f2d..a3f433ca4c 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -14,8 +14,9 @@
#include "gettext.h"
#include "hex.h"
#include "notes.h"
+#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "path.h"
#include "pretty.h"
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 58a9b16126..67941c8a60 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -32,7 +32,7 @@
#include "list.h"
#include "packfile.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "replace-object.h"
#include "dir.h"
#include "midx.h"
@@ -41,6 +41,10 @@
#include "promisor-remote.h"
#include "pack-mtimes.h"
#include "parse-options.h"
+#include "blob.h"
+#include "tree.h"
+#include "path-walk.h"
+#include "trace2.h"
/*
* Objects we are going to pack are collected in the `to_pack` structure.
@@ -183,9 +187,15 @@ static inline void oe_set_delta_size(struct packing_data *pack,
#define SET_DELTA_CHILD(obj, val) oe_set_delta_child(&to_pack, obj, val)
#define SET_DELTA_SIBLING(obj, val) oe_set_delta_sibling(&to_pack, obj, val)
-static const char *pack_usage[] = {
- N_("git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"),
- N_("git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"),
+static const char *const pack_usage[] = {
+ N_("git pack-objects [-q | --progress | --all-progress] [--all-progress-implied]\n"
+ " [--no-reuse-delta] [--delta-base-offset] [--non-empty]\n"
+ " [--local] [--incremental] [--window=<n>] [--depth=<n>]\n"
+ " [--revs [--unpacked | --all]] [--keep-pack=<pack-name>]\n"
+ " [--cruft] [--cruft-expiration=<time>]\n"
+ " [--stdout [--filter=<filter-spec>] | <base-name>]\n"
+ " [--shallow] [--keep-true-parents] [--[no-]sparse]\n"
+ " [--name-hash-version=<n>] [--path-walk] < <object-list>"),
NULL
};
@@ -200,12 +210,14 @@ static int keep_unreachable, unpack_unreachable, include_tag;
static timestamp_t unpack_unreachable_expiration;
static int pack_loose_unreachable;
static int cruft;
+static int shallow = 0;
static timestamp_t cruft_expiration;
static int local;
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;
@@ -217,6 +229,7 @@ static int delta_search_threads;
static int pack_to_stdout;
static int sparse;
static int thin;
+static int path_walk = -1;
static int num_preferred_base;
static struct progress *progress_state;
@@ -499,7 +512,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
if (!usable_delta) {
if (oe_type(entry) == OBJ_BLOB &&
- oe_size_greater_than(&to_pack, entry, big_file_threshold) &&
+ oe_size_greater_than(&to_pack, entry,
+ repo_settings_get_big_file_threshold(the_repository)) &&
(st = open_istream(the_repository, &entry->idx.oid, &type,
&size, NULL)) != NULL)
buf = NULL;
@@ -1311,9 +1325,10 @@ static void write_pack_file(void)
char *pack_tmp_name = NULL;
if (pack_to_stdout)
- f = hashfd_throughput(1, "<stdout>", progress_state);
+ f = hashfd_throughput(the_repository->hash_algo, 1,
+ "<stdout>", progress_state);
else
- f = create_tmp_packfile(&pack_tmp_name);
+ f = create_tmp_packfile(the_repository, &pack_tmp_name);
offset = write_pack_header(f, nr_remaining);
@@ -1397,7 +1412,8 @@ static void write_pack_file(void)
if (write_bitmap_index) {
bitmap_writer_init(&bitmap_writer,
- the_repository, &to_pack);
+ the_repository, &to_pack,
+ NULL);
bitmap_writer_set_checksum(&bitmap_writer, hash);
bitmap_writer_build_type_index(&bitmap_writer,
written_list);
@@ -1406,7 +1422,7 @@ static void write_pack_file(void)
if (cruft)
pack_idx_opts.flags |= WRITE_MTIMES;
- stage_tmp_packfiles(the_hash_algo, &tmpname,
+ stage_tmp_packfiles(the_repository, &tmpname,
pack_tmp_name, written_list,
nr_written, &to_pack,
&pack_idx_opts, hash,
@@ -1502,8 +1518,60 @@ static int have_duplicate_entry(const struct object_id *oid,
return 1;
}
+static int want_cruft_object_mtime(struct repository *r,
+ const struct object_id *oid,
+ unsigned flags, uint32_t mtime)
+{
+ struct packed_git **cache;
+
+ for (cache = kept_pack_cache(r, flags); *cache; cache++) {
+ struct packed_git *p = *cache;
+ off_t ofs;
+ uint32_t candidate_mtime;
+
+ ofs = find_pack_entry_one(oid, p);
+ if (!ofs)
+ continue;
+
+ /*
+ * We have a copy of the object 'oid' in a non-cruft
+ * pack. We can avoid packing an additional copy
+ * regardless of what the existing copy's mtime is since
+ * it is outside of a cruft pack.
+ */
+ if (!p->is_cruft)
+ return 0;
+
+ /*
+ * If we have a copy of the object 'oid' in a cruft
+ * pack, then either read the cruft pack's mtime for
+ * that object, or, if that can't be loaded, assume the
+ * pack's mtime itself.
+ */
+ if (!load_pack_mtimes(p)) {
+ uint32_t pos;
+ if (offset_to_pack_pos(p, ofs, &pos) < 0)
+ continue;
+ candidate_mtime = nth_packed_mtime(p, pos);
+ } else {
+ candidate_mtime = p->mtime;
+ }
+
+ /*
+ * We have a surviving copy of the object in a cruft
+ * pack whose mtime is greater than or equal to the one
+ * we are considering. We can thus avoid packing an
+ * additional copy of that object.
+ */
+ if (mtime <= candidate_mtime)
+ return 0;
+ }
+
+ return -1;
+}
+
static int want_found_object(const struct object_id *oid, int exclude,
- struct packed_git *p)
+ struct packed_git *p, uint32_t mtime)
{
if (exclude)
return 1;
@@ -1553,12 +1621,29 @@ static int want_found_object(const struct object_id *oid, int exclude,
if (ignore_packed_keep_in_core)
flags |= IN_CORE_KEEP_PACKS;
- if (ignore_packed_keep_on_disk && p->pack_keep)
- return 0;
- if (ignore_packed_keep_in_core && p->pack_keep_in_core)
- return 0;
- if (has_object_kept_pack(p->repo, oid, flags))
- return 0;
+ /*
+ * If the object is in a pack that we want to ignore, *and* we
+ * don't have any cruft packs that are being retained, we can
+ * abort quickly.
+ */
+ if (!ignore_packed_keep_in_core_has_cruft) {
+ if (ignore_packed_keep_on_disk && p->pack_keep)
+ return 0;
+ if (ignore_packed_keep_in_core && p->pack_keep_in_core)
+ return 0;
+ if (has_object_kept_pack(p->repo, oid, flags))
+ return 0;
+ } else {
+ /*
+ * But if there is at least one cruft pack which
+ * is being kept, we only want to include the
+ * provided object if it has a strictly greater
+ * mtime than any existing cruft copy.
+ */
+ if (!want_cruft_object_mtime(p->repo, oid, flags,
+ mtime))
+ return 0;
+ }
}
/*
@@ -1577,7 +1662,8 @@ static int want_object_in_pack_one(struct packed_git *p,
const struct object_id *oid,
int exclude,
struct packed_git **found_pack,
- off_t *found_offset)
+ off_t *found_offset,
+ uint32_t found_mtime)
{
off_t offset;
@@ -1593,7 +1679,7 @@ static int want_object_in_pack_one(struct packed_git *p,
*found_offset = offset;
*found_pack = p;
}
- return want_found_object(oid, exclude, p);
+ return want_found_object(oid, exclude, p, found_mtime);
}
return -1;
}
@@ -1607,10 +1693,11 @@ static int want_object_in_pack_one(struct packed_git *p,
* function finds if there is any pack that has the object and returns the pack
* and its offset in these variables.
*/
-static int want_object_in_pack(const struct object_id *oid,
- int exclude,
- struct packed_git **found_pack,
- off_t *found_offset)
+static int want_object_in_pack_mtime(const struct object_id *oid,
+ int exclude,
+ struct packed_git **found_pack,
+ off_t *found_offset,
+ uint32_t found_mtime)
{
int want;
struct list_head *pos;
@@ -1625,7 +1712,8 @@ static int want_object_in_pack(const struct object_id *oid,
* are present we will determine the answer right now.
*/
if (*found_pack) {
- want = want_found_object(oid, exclude, *found_pack);
+ want = want_found_object(oid, exclude, *found_pack,
+ found_mtime);
if (want != -1)
return want;
@@ -1636,7 +1724,7 @@ static int want_object_in_pack(const struct object_id *oid,
for (m = get_multi_pack_index(the_repository); m; m = m->next) {
struct pack_entry e;
if (fill_midx_entry(the_repository, oid, &e, m)) {
- want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset);
+ want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime);
if (want != -1)
return want;
}
@@ -1644,7 +1732,7 @@ static int want_object_in_pack(const struct object_id *oid,
list_for_each(pos, get_packed_git_mru(the_repository)) {
struct packed_git *p = list_entry(pos, struct packed_git, mru);
- want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset);
+ want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
if (!exclude && want > 0)
list_move(&p->mru,
get_packed_git_mru(the_repository));
@@ -1674,6 +1762,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,
@@ -1735,7 +1832,8 @@ static int add_object_entry(const struct object_id *oid, enum object_type type,
static int add_object_entry_from_bitmap(const struct object_id *oid,
enum object_type type,
int flags UNUSED, uint32_t name_hash,
- struct packed_git *pack, off_t offset)
+ struct packed_git *pack, off_t offset,
+ void *payload UNUSED)
{
display_progress(progress_state, ++nr_seen);
@@ -2453,7 +2551,8 @@ static void get_object_details(void)
struct object_entry *entry = sorted_by_offset[i];
check_object(entry, i);
if (entry->type_valid &&
- oe_size_greater_than(&to_pack, entry, big_file_threshold))
+ oe_size_greater_than(&to_pack, entry,
+ repo_settings_get_big_file_threshold(the_repository)))
entry->no_try_delta = 1;
display_progress(progress_state, i + 1);
}
@@ -2954,6 +3053,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
struct thread_params {
pthread_t thread;
struct object_entry **list;
+ struct packing_region *regions;
unsigned list_size;
unsigned remaining;
int window;
@@ -3196,6 +3296,242 @@ static int add_ref_tag(const char *tag UNUSED, const char *referent UNUSED, cons
return 0;
}
+static int should_attempt_deltas(struct object_entry *entry)
+{
+ if (DELTA(entry))
+ /* This happens if we decided to reuse existing
+ * delta from a pack. "reuse_delta &&" is implied.
+ */
+ return 0;
+
+ if (!entry->type_valid ||
+ oe_size_less_than(&to_pack, entry, 50))
+ return 0;
+
+ if (entry->no_try_delta)
+ return 0;
+
+ if (!entry->preferred_base) {
+ if (oe_type(entry) < 0)
+ die(_("unable to get type of object %s"),
+ oid_to_hex(&entry->idx.oid));
+ } else if (oe_type(entry) < 0) {
+ /*
+ * This object is not found, but we
+ * don't have to include it anyway.
+ */
+ return 0;
+ }
+
+ return 1;
+}
+
+static void find_deltas_for_region(struct object_entry *list,
+ struct packing_region *region,
+ unsigned int *processed)
+{
+ struct object_entry **delta_list;
+ unsigned int delta_list_nr = 0;
+
+ ALLOC_ARRAY(delta_list, region->nr);
+ for (size_t i = 0; i < region->nr; i++) {
+ struct object_entry *entry = list + region->start + i;
+ if (should_attempt_deltas(entry))
+ delta_list[delta_list_nr++] = entry;
+ }
+
+ QSORT(delta_list, delta_list_nr, type_size_sort);
+ find_deltas(delta_list, &delta_list_nr, window, depth, processed);
+ free(delta_list);
+}
+
+static void find_deltas_by_region(struct object_entry *list,
+ struct packing_region *regions,
+ size_t start, size_t nr)
+{
+ unsigned int processed = 0;
+ size_t progress_nr;
+
+ if (!nr)
+ return;
+
+ progress_nr = regions[nr - 1].start + regions[nr - 1].nr;
+
+ if (progress)
+ progress_state = start_progress(the_repository,
+ _("Compressing objects by path"),
+ progress_nr);
+
+ while (nr--)
+ find_deltas_for_region(list,
+ &regions[start++],
+ &processed);
+
+ display_progress(progress_state, progress_nr);
+ stop_progress(&progress_state);
+}
+
+static void *threaded_find_deltas_by_path(void *arg)
+{
+ struct thread_params *me = arg;
+
+ progress_lock();
+ while (me->remaining) {
+ while (me->remaining) {
+ progress_unlock();
+ find_deltas_for_region(to_pack.objects,
+ me->regions,
+ me->processed);
+ progress_lock();
+ me->remaining--;
+ me->regions++;
+ }
+
+ me->working = 0;
+ pthread_cond_signal(&progress_cond);
+ progress_unlock();
+
+ /*
+ * We must not set ->data_ready before we wait on the
+ * condition because the main thread may have set it to 1
+ * before we get here. In order to be sure that new
+ * work is available if we see 1 in ->data_ready, it
+ * was initialized to 0 before this thread was spawned
+ * and we reset it to 0 right away.
+ */
+ pthread_mutex_lock(&me->mutex);
+ while (!me->data_ready)
+ pthread_cond_wait(&me->cond, &me->mutex);
+ me->data_ready = 0;
+ pthread_mutex_unlock(&me->mutex);
+
+ progress_lock();
+ }
+ progress_unlock();
+ /* leave ->working 1 so that this doesn't get more work assigned */
+ return NULL;
+}
+
+static void ll_find_deltas_by_region(struct object_entry *list,
+ struct packing_region *regions,
+ uint32_t start, uint32_t nr)
+{
+ struct thread_params *p;
+ int i, ret, active_threads = 0;
+ unsigned int processed = 0;
+ uint32_t progress_nr;
+ init_threaded_search();
+
+ if (!nr)
+ return;
+
+ progress_nr = regions[nr - 1].start + regions[nr - 1].nr;
+ if (delta_search_threads <= 1) {
+ find_deltas_by_region(list, regions, start, nr);
+ cleanup_threaded_search();
+ return;
+ }
+
+ if (progress > pack_to_stdout)
+ fprintf_ln(stderr,
+ Q_("Path-based delta compression using up to %d thread",
+ "Path-based delta compression using up to %d threads",
+ delta_search_threads),
+ delta_search_threads);
+ CALLOC_ARRAY(p, delta_search_threads);
+
+ if (progress)
+ progress_state = start_progress(the_repository,
+ _("Compressing objects by path"),
+ progress_nr);
+ /* Partition the work amongst work threads. */
+ for (i = 0; i < delta_search_threads; i++) {
+ unsigned sub_size = nr / (delta_search_threads - i);
+
+ p[i].window = window;
+ p[i].depth = depth;
+ p[i].processed = &processed;
+ p[i].working = 1;
+ p[i].data_ready = 0;
+
+ p[i].regions = regions;
+ p[i].list_size = sub_size;
+ p[i].remaining = sub_size;
+
+ regions += sub_size;
+ nr -= sub_size;
+ }
+
+ /* Start work threads. */
+ for (i = 0; i < delta_search_threads; i++) {
+ if (!p[i].list_size)
+ continue;
+ pthread_mutex_init(&p[i].mutex, NULL);
+ pthread_cond_init(&p[i].cond, NULL);
+ ret = pthread_create(&p[i].thread, NULL,
+ threaded_find_deltas_by_path, &p[i]);
+ if (ret)
+ die(_("unable to create thread: %s"), strerror(ret));
+ active_threads++;
+ }
+
+ /*
+ * Now let's wait for work completion. Each time a thread is done
+ * with its work, we steal half of the remaining work from the
+ * thread with the largest number of unprocessed objects and give
+ * it to that newly idle thread. This ensure good load balancing
+ * until the remaining object list segments are simply too short
+ * to be worth splitting anymore.
+ */
+ while (active_threads) {
+ struct thread_params *target = NULL;
+ struct thread_params *victim = NULL;
+ unsigned sub_size = 0;
+
+ progress_lock();
+ for (;;) {
+ for (i = 0; !target && i < delta_search_threads; i++)
+ if (!p[i].working)
+ target = &p[i];
+ if (target)
+ break;
+ pthread_cond_wait(&progress_cond, &progress_mutex);
+ }
+
+ for (i = 0; i < delta_search_threads; i++)
+ if (p[i].remaining > 2*window &&
+ (!victim || victim->remaining < p[i].remaining))
+ victim = &p[i];
+ if (victim) {
+ sub_size = victim->remaining / 2;
+ target->regions = victim->regions + victim->remaining - sub_size;
+ victim->list_size -= sub_size;
+ victim->remaining -= sub_size;
+ }
+ target->list_size = sub_size;
+ target->remaining = sub_size;
+ target->working = 1;
+ progress_unlock();
+
+ pthread_mutex_lock(&target->mutex);
+ target->data_ready = 1;
+ pthread_cond_signal(&target->cond);
+ pthread_mutex_unlock(&target->mutex);
+
+ if (!sub_size) {
+ pthread_join(target->thread, NULL);
+ pthread_cond_destroy(&target->cond);
+ pthread_mutex_destroy(&target->mutex);
+ active_threads--;
+ }
+ }
+ cleanup_threaded_search();
+ free(p);
+
+ display_progress(progress_state, progress_nr);
+ stop_progress(&progress_state);
+}
+
static void prepare_pack(int window, int depth)
{
struct object_entry **delta_list;
@@ -3220,39 +3556,21 @@ static void prepare_pack(int window, int depth)
if (!to_pack.nr_objects || !window || !depth)
return;
+ if (path_walk)
+ ll_find_deltas_by_region(to_pack.objects, to_pack.regions,
+ 0, to_pack.nr_regions);
+
ALLOC_ARRAY(delta_list, to_pack.nr_objects);
nr_deltas = n = 0;
for (i = 0; i < to_pack.nr_objects; i++) {
struct object_entry *entry = to_pack.objects + i;
- if (DELTA(entry))
- /* This happens if we decided to reuse existing
- * delta from a pack. "reuse_delta &&" is implied.
- */
- continue;
-
- if (!entry->type_valid ||
- oe_size_less_than(&to_pack, entry, 50))
+ if (!should_attempt_deltas(entry))
continue;
- if (entry->no_try_delta)
- continue;
-
- if (!entry->preferred_base) {
+ if (!entry->preferred_base)
nr_deltas++;
- if (oe_type(entry) < 0)
- die(_("unable to get type of object %s"),
- oid_to_hex(&entry->idx.oid));
- } else {
- if (oe_type(entry) < 0) {
- /*
- * This object is not found, but we
- * don't have to include it anyway.
- */
- continue;
- }
- }
delta_list[n++] = entry;
}
@@ -3606,7 +3924,7 @@ static void add_cruft_object_entry(const struct object_id *oid, enum object_type
entry->no_try_delta = no_try_delta(name);
}
} else {
- if (!want_object_in_pack(oid, 0, &pack, &offset))
+ if (!want_object_in_pack_mtime(oid, 0, &pack, &offset, mtime))
return;
if (!pack && type == OBJ_BLOB && !has_loose_object(oid)) {
/*
@@ -3680,6 +3998,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;
}
}
@@ -3844,7 +4164,7 @@ static void show_commit(struct commit *commit, void *data UNUSED)
index_commit_for_bitmap(commit);
if (use_delta_islands)
- propagate_island_marks(commit);
+ propagate_island_marks(the_repository, commit);
}
static void show_object(struct object *obj, const char *name,
@@ -4160,7 +4480,7 @@ static int mark_bitmap_preferred_tip(const char *refname,
if (!peel_iterated_oid(the_repository, oid, &peeled))
oid = &peeled;
- object = parse_object_or_die(oid, refname);
+ object = parse_object_or_die(the_repository, oid, refname);
if (object->type == OBJ_COMMIT)
object->flags |= NEEDS_BITMAP;
@@ -4183,6 +4503,93 @@ static void mark_bitmap_preferred_tips(void)
}
}
+static inline int is_oid_uninteresting(struct repository *repo,
+ struct object_id *oid)
+{
+ struct object *o = lookup_object(repo, oid);
+ return !o || (o->flags & UNINTERESTING);
+}
+
+static int add_objects_by_path(const char *path,
+ struct oid_array *oids,
+ enum object_type type,
+ void *data)
+{
+ size_t oe_start = to_pack.nr_objects;
+ size_t oe_end;
+ unsigned int *processed = data;
+
+ /*
+ * First, add all objects to the packing data, including the ones
+ * marked UNINTERESTING (translated to 'exclude') as they can be
+ * used as delta bases.
+ */
+ for (size_t i = 0; i < oids->nr; i++) {
+ int exclude;
+ struct object_info oi = OBJECT_INFO_INIT;
+ struct object_id *oid = &oids->oid[i];
+
+ /* Skip objects that do not exist locally. */
+ if ((exclude_promisor_objects || arg_missing_action != MA_ERROR) &&
+ oid_object_info_extended(the_repository, oid, &oi,
+ OBJECT_INFO_FOR_PREFETCH) < 0)
+ continue;
+
+ exclude = is_oid_uninteresting(the_repository, oid);
+
+ if (exclude && !thin)
+ continue;
+
+ add_object_entry(oid, type, path, exclude);
+ }
+
+ oe_end = to_pack.nr_objects;
+
+ /* We can skip delta calculations if it is a no-op. */
+ if (oe_end == oe_start || !window)
+ return 0;
+
+ ALLOC_GROW(to_pack.regions,
+ to_pack.nr_regions + 1,
+ to_pack.nr_regions_alloc);
+
+ to_pack.regions[to_pack.nr_regions].start = oe_start;
+ to_pack.regions[to_pack.nr_regions].nr = oe_end - oe_start;
+ to_pack.nr_regions++;
+
+ *processed += oids->nr;
+ display_progress(progress_state, *processed);
+
+ return 0;
+}
+
+static void get_object_list_path_walk(struct rev_info *revs)
+{
+ struct path_walk_info info = PATH_WALK_INFO_INIT;
+ unsigned int processed = 0;
+ int result;
+
+ info.revs = revs;
+ info.path_fn = add_objects_by_path;
+ info.path_fn_data = &processed;
+
+ /*
+ * Allow the --[no-]sparse option to be interesting here, if only
+ * for testing purposes. Paths with no interesting objects will not
+ * contribute to the resulting pack, but only create noisy preferred
+ * base objects.
+ */
+ info.prune_all_uninteresting = sparse;
+ info.edge_aggressive = shallow;
+
+ trace2_region_enter("pack-objects", "path-walk", revs->repo);
+ result = walk_objects_by_path(&info);
+ trace2_region_leave("pack-objects", "path-walk", revs->repo);
+
+ if (result)
+ die(_("failed to pack objects via path-walk"));
+}
+
static void get_object_list(struct rev_info *revs, int ac, const char **av)
{
struct setup_revision_opt s_r_opt = {
@@ -4238,15 +4645,19 @@ static void get_object_list(struct rev_info *revs, int ac, const char **av)
if (write_bitmap_index)
mark_bitmap_preferred_tips();
- if (prepare_revision_walk(revs))
- die(_("revision walk setup failed"));
- mark_edges_uninteresting(revs, show_edge, sparse);
-
if (!fn_show_object)
fn_show_object = show_object;
- traverse_commit_list(revs,
- show_commit, fn_show_object,
- NULL);
+
+ if (path_walk) {
+ get_object_list_path_walk(revs);
+ } else {
+ if (prepare_revision_walk(revs))
+ die(_("revision walk setup failed"));
+ mark_edges_uninteresting(revs, show_edge, sparse);
+ traverse_commit_list(revs,
+ show_commit, fn_show_object,
+ NULL);
+ }
if (unpack_unreachable_expiration) {
revs->ignore_missing_links = 1;
@@ -4375,7 +4786,6 @@ int cmd_pack_objects(int argc,
struct repository *repo UNUSED)
{
int use_internal_rev_list = 0;
- int shallow = 0;
int all_progress_implied = 0;
struct strvec rp = STRVEC_INIT;
int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
@@ -4399,16 +4809,16 @@ int cmd_pack_objects(int argc,
OPT_CALLBACK_F(0, "index-version", &pack_idx_opts, N_("<version>[,<offset>]"),
N_("write the pack index file in the specified idx format version"),
PARSE_OPT_NONEG, option_parse_index_version),
- OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
- N_("maximum size of each output pack file")),
+ OPT_UNSIGNED(0, "max-pack-size", &pack_size_limit,
+ N_("maximum size of each output pack file")),
OPT_BOOL(0, "local", &local,
N_("ignore borrowed objects from alternate object store")),
OPT_BOOL(0, "incremental", &incremental,
N_("ignore packed objects")),
OPT_INTEGER(0, "window", &window,
N_("limit pack window by objects")),
- OPT_MAGNITUDE(0, "window-memory", &window_memory_limit,
- N_("limit pack window by memory in addition to object limit")),
+ OPT_UNSIGNED(0, "window-memory", &window_memory_limit,
+ N_("limit pack window by memory in addition to object limit")),
OPT_INTEGER(0, "depth", &depth,
N_("maximum length of delta chain allowed in the resulting pack")),
OPT_BOOL(0, "reuse-delta", &reuse_delta,
@@ -4456,6 +4866,8 @@ int cmd_pack_objects(int argc,
N_("use the sparse reachability algorithm")),
OPT_BOOL(0, "thin", &thin,
N_("create thin packs")),
+ OPT_BOOL(0, "path-walk", &path_walk,
+ N_("use the path-walk API to walk objects when possible")),
OPT_BOOL(0, "shallow", &shallow,
N_("create packs suitable for shallow fetches")),
OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk,
@@ -4525,6 +4937,17 @@ int cmd_pack_objects(int argc,
if (pack_to_stdout != !base_name || argc)
usage_with_options(pack_usage, pack_objects_options);
+ if (path_walk < 0) {
+ if (use_bitmap_index > 0 ||
+ !use_internal_rev_list)
+ path_walk = 0;
+ else if (the_repository->gitdir &&
+ the_repository->settings.pack_use_path_walk)
+ path_walk = 1;
+ else
+ path_walk = git_env_bool("GIT_TEST_PACK_PATH_WALK", 0);
+ }
+
if (depth < 0)
depth = 0;
if (depth >= (1 << OE_DEPTH_BITS)) {
@@ -4541,7 +4964,28 @@ int cmd_pack_objects(int argc,
window = 0;
strvec_push(&rp, "pack-objects");
- if (thin) {
+
+ if (path_walk) {
+ const char *option = NULL;
+ if (filter_options.choice)
+ option = "--filter";
+ else if (use_delta_islands)
+ option = "--delta-islands";
+
+ if (option) {
+ warning(_("cannot use %s with %s"),
+ option, "--path-walk");
+ path_walk = 0;
+ }
+ }
+ if (path_walk) {
+ strvec_push(&rp, "--boundary");
+ /*
+ * We must disable the bitmaps because we are removing
+ * the --objects / --objects-edge[-aggressive] options.
+ */
+ use_bitmap_index = 0;
+ } else if (thin) {
use_internal_rev_list = 1;
strvec_push(&rp, shallow
? "--objects-edge-aggressive"
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 3febe732f8..5d1fc78176 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -13,7 +13,7 @@
#include "hex.h"
#include "packfile.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "strbuf.h"
#define BLKSIZE 512
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/prune.c b/builtin/prune.c
index 1c357fffd8..e930caa0c0 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -17,7 +17,7 @@
#include "replace-object.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "shallow.h"
static const char * const prune_usage[] = {
@@ -185,7 +185,7 @@ int cmd_prune(int argc,
const char *name = *argv++;
if (!repo_get_oid(the_repository, name, &oid)) {
- struct object *object = parse_object_or_die(&oid,
+ struct object *object = parse_object_or_die(the_repository, &oid,
name);
add_pending_object(&revs, object, "");
}
diff --git a/builtin/pull.c b/builtin/pull.c
index 9c4a00620a..a1ebc6ad33 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -738,7 +738,8 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
const char *spec_src;
const char *merge_branch;
- refspec_item_init_or_die(&spec, refspec, REFSPEC_FETCH);
+ if (!refspec_item_init_fetch(&spec, refspec))
+ die(_("invalid refspec '%s'"), refspec);
spec_src = spec.src;
if (!*spec_src || !strcmp(spec_src, "HEAD"))
spec_src = "HEAD";
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index d2a807a828..a8f352f7cd 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -135,9 +135,14 @@ int cmd_read_tree(int argc,
N_("3-way merge in presence of adds and removes")),
OPT_BOOL(0, "reset", &opts.reset,
N_("same as -m, but discard unmerged entries")),
- { OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),
- N_("read the tree into the index under <subdirectory>/"),
- PARSE_OPT_NONEG },
+ {
+ .type = OPTION_STRING,
+ .long_name = "prefix",
+ .value = &opts.prefix,
+ .argh = N_("<subdirectory>/"),
+ .help = N_("read the tree into the index under <subdirectory>/"),
+ .flags = PARSE_OPT_NONEG,
+ },
OPT_BOOL('u', NULL, &opts.update,
N_("update working tree with merge result")),
OPT_CALLBACK_F(0, "exclude-per-directory", &opts,
diff --git a/builtin/rebase.c b/builtin/rebase.c
index d4715ed35d..2e8c4ee678 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -267,7 +267,8 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name,
{
FILE *interactive;
- if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
+ if (!is_directory(merge_dir()) &&
+ safe_create_dir_in_gitdir(the_repository, merge_dir()))
return error_errno(_("could not create temporary %s"), merge_dir());
refs_delete_reflog(get_main_ref_store(the_repository), "REBASE_HEAD");
@@ -925,7 +926,7 @@ static void fill_branch_base(struct rebase_options *options,
options->orig_head, &merge_bases) < 0)
exit(128);
if (!merge_bases || merge_bases->next)
- oidcpy(branch_base, null_oid());
+ oidcpy(branch_base, null_oid(the_hash_algo));
else
oidcpy(branch_base, &merge_bases->item->object.oid);
@@ -1122,9 +1123,15 @@ int cmd_rebase(int argc,
OPT_BIT('v', "verbose", &options.flags,
N_("display a diffstat of what changed upstream"),
REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
- {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,
- N_("do not show diffstat of what changed upstream"),
- PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
+ {
+ .type = OPTION_NEGBIT,
+ .short_name = 'n',
+ .long_name = "no-stat",
+ .value = &options.flags,
+ .help = N_("do not show diffstat of what changed upstream"),
+ .flags = PARSE_OPT_NOARG,
+ .defval = REBASE_DIFFSTAT,
+ },
OPT_BOOL(0, "signoff", &options.signoff,
N_("add a Signed-off-by trailer to each commit")),
OPT_BOOL(0, "committer-date-is-author-date",
@@ -1190,9 +1197,16 @@ int cmd_rebase(int argc,
OPT_BOOL(0, "update-refs", &options.update_refs,
N_("update branches that point to commits "
"that are being rebased")),
- { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
- N_("GPG-sign commits"),
- PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &gpg_sign,
+ .argh = N_("key-id"),
+ .help = N_("GPG-sign commits"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
OPT_AUTOSTASH(&options.autostash),
OPT_STRING_LIST('x', "exec", &options.exec, N_("exec"),
N_("add exec lines after each commit of the "
@@ -1575,11 +1589,6 @@ int cmd_rebase(int argc,
options.default_backend);
}
- if (options.type == REBASE_MERGE &&
- !options.strategy &&
- getenv("GIT_TEST_MERGE_ALGORITHM"))
- options.strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
-
switch (options.type) {
case REBASE_MERGE:
options.state_dir = merge_dir();
@@ -1843,7 +1852,7 @@ int cmd_rebase(int argc,
strbuf_addf(&msg, "%s (start): checkout %s",
options.reflog_action, options.onto_name);
ropts.oid = &options.onto->object.oid;
- ropts.orig_head = &options.orig_head->object.oid,
+ ropts.orig_head = &options.orig_head->object.oid;
ropts.flags = RESET_HEAD_DETACH | RESET_ORIG_HEAD |
RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
ropts.head_msg = msg.buf;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 7b28fc9df6..a317d6c278 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -31,8 +31,9 @@
#include "tmp-objdir.h"
#include "oidset.h"
#include "packfile.h"
+#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "path.h"
#include "protocol.h"
#include "commit-reach.h"
@@ -80,6 +81,7 @@ static int prefer_ofs_delta = 1;
static int auto_update_server_info;
static int auto_gc = 1;
static int reject_thin;
+static int skip_connectivity_check;
static int stateless_rpc;
static const char *service_dir;
static const char *head_name;
@@ -363,7 +365,7 @@ static void write_head_info(void)
strvec_clear(&excludes_vector);
if (!sent_capabilities)
- show_ref("capabilities^{}", null_oid());
+ show_ref("capabilities^{}", null_oid(the_hash_algo));
advertise_shallow_grafts(1);
@@ -1505,7 +1507,9 @@ static const char *update(struct command *cmd, struct shallow_info *si)
}
}
- if (!is_null_oid(new_oid) && !repo_has_object_file(the_repository, new_oid)) {
+ if (!is_null_oid(new_oid) &&
+ !has_object(the_repository, new_oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) {
error("unpack should have generated %s, "
"but I can't find it!", oid_to_hex(new_oid));
ret = "bad pack";
@@ -1935,27 +1939,29 @@ static void execute_commands(struct command *commands,
return;
}
- if (use_sideband) {
- memset(&muxer, 0, sizeof(muxer));
- muxer.proc = copy_to_sideband;
- muxer.in = -1;
- if (!start_async(&muxer))
- err_fd = muxer.in;
- /* ...else, continue without relaying sideband */
- }
+ if (!skip_connectivity_check) {
+ if (use_sideband) {
+ memset(&muxer, 0, sizeof(muxer));
+ muxer.proc = copy_to_sideband;
+ muxer.in = -1;
+ if (!start_async(&muxer))
+ err_fd = muxer.in;
+ /* ...else, continue without relaying sideband */
+ }
- data.cmds = commands;
- data.si = si;
- opt.err_fd = err_fd;
- opt.progress = err_fd && !quiet;
- opt.env = tmp_objdir_env(tmp_objdir);
- opt.exclude_hidden_refs_section = "receive";
+ data.cmds = commands;
+ data.si = si;
+ opt.err_fd = err_fd;
+ opt.progress = err_fd && !quiet;
+ opt.env = tmp_objdir_env(tmp_objdir);
+ opt.exclude_hidden_refs_section = "receive";
- if (check_connected(iterate_receive_command_list, &data, &opt))
- set_connectivity_errors(commands, si);
+ if (check_connected(iterate_receive_command_list, &data, &opt))
+ set_connectivity_errors(commands, si);
- if (use_sideband)
- finish_async(&muxer);
+ if (use_sideband)
+ finish_async(&muxer);
+ }
reject_updates_to_hidden(commands);
@@ -2516,6 +2522,7 @@ int cmd_receive_pack(int argc,
struct option options[] = {
OPT__QUIET(&quiet, N_("quiet")),
+ OPT_HIDDEN_BOOL(0, "skip-connectivity-check", &skip_connectivity_check, NULL),
OPT_HIDDEN_BOOL(0, "stateless-rpc", &stateless_rpc, NULL),
OPT_HIDDEN_BOOL(0, "http-backend-info-refs", &advertise_refs, NULL),
OPT_ALIAS(0, "advertise-refs", "http-backend-info-refs"),
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 95f264989b..3acaf3e32c 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -29,6 +29,9 @@
#define BUILTIN_REFLOG_EXISTS_USAGE \
N_("git reflog exists <ref>")
+#define BUILTIN_REFLOG_DROP_USAGE \
+ N_("git reflog drop [--all [--single-worktree] | <refs>...]")
+
static const char *const reflog_show_usage[] = {
BUILTIN_REFLOG_SHOW_USAGE,
NULL,
@@ -54,18 +57,21 @@ static const char *const reflog_exists_usage[] = {
NULL,
};
+static const char *const reflog_drop_usage[] = {
+ BUILTIN_REFLOG_DROP_USAGE,
+ NULL,
+};
+
static const char *const reflog_usage[] = {
BUILTIN_REFLOG_SHOW_USAGE,
BUILTIN_REFLOG_LIST_USAGE,
BUILTIN_REFLOG_EXPIRE_USAGE,
BUILTIN_REFLOG_DELETE_USAGE,
+ BUILTIN_REFLOG_DROP_USAGE,
BUILTIN_REFLOG_EXISTS_USAGE,
NULL
};
-static timestamp_t default_reflog_expire;
-static timestamp_t default_reflog_expire_unreachable;
-
struct worktree_reflogs {
struct worktree *worktree;
struct string_list reflogs;
@@ -91,131 +97,19 @@ static int collect_reflog(const char *ref, void *cb_data)
return 0;
}
-static struct reflog_expire_cfg {
- struct reflog_expire_cfg *next;
- timestamp_t expire_total;
- timestamp_t expire_unreachable;
- char pattern[FLEX_ARRAY];
-} *reflog_expire_cfg, **reflog_expire_cfg_tail;
-
-static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
-{
- struct reflog_expire_cfg *ent;
-
- if (!reflog_expire_cfg_tail)
- reflog_expire_cfg_tail = &reflog_expire_cfg;
-
- for (ent = reflog_expire_cfg; ent; ent = ent->next)
- if (!xstrncmpz(ent->pattern, pattern, len))
- return ent;
-
- FLEX_ALLOC_MEM(ent, pattern, pattern, len);
- *reflog_expire_cfg_tail = ent;
- reflog_expire_cfg_tail = &(ent->next);
- return ent;
-}
-
-/* expiry timer slot */
-#define EXPIRE_TOTAL 01
-#define EXPIRE_UNREACH 02
-
-static int reflog_expire_config(const char *var, const char *value,
- const struct config_context *ctx, void *cb)
-{
- const char *pattern, *key;
- size_t pattern_len;
- timestamp_t expire;
- int slot;
- struct reflog_expire_cfg *ent;
-
- if (parse_config_key(var, "gc", &pattern, &pattern_len, &key) < 0)
- return git_default_config(var, value, ctx, cb);
-
- if (!strcmp(key, "reflogexpire")) {
- slot = EXPIRE_TOTAL;
- if (git_config_expiry_date(&expire, var, value))
- return -1;
- } else if (!strcmp(key, "reflogexpireunreachable")) {
- slot = EXPIRE_UNREACH;
- if (git_config_expiry_date(&expire, var, value))
- return -1;
- } else
- return git_default_config(var, value, ctx, cb);
-
- if (!pattern) {
- switch (slot) {
- case EXPIRE_TOTAL:
- default_reflog_expire = expire;
- break;
- case EXPIRE_UNREACH:
- default_reflog_expire_unreachable = expire;
- break;
- }
- return 0;
- }
-
- ent = find_cfg_ent(pattern, pattern_len);
- if (!ent)
- return -1;
- switch (slot) {
- case EXPIRE_TOTAL:
- ent->expire_total = expire;
- break;
- case EXPIRE_UNREACH:
- ent->expire_unreachable = expire;
- break;
- }
- return 0;
-}
-
-static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, const char *ref)
-{
- struct reflog_expire_cfg *ent;
-
- if (cb->explicit_expiry == (EXPIRE_TOTAL|EXPIRE_UNREACH))
- return; /* both given explicitly -- nothing to tweak */
-
- for (ent = reflog_expire_cfg; ent; ent = ent->next) {
- if (!wildmatch(ent->pattern, ref, 0)) {
- if (!(cb->explicit_expiry & EXPIRE_TOTAL))
- cb->expire_total = ent->expire_total;
- if (!(cb->explicit_expiry & EXPIRE_UNREACH))
- cb->expire_unreachable = ent->expire_unreachable;
- return;
- }
- }
-
- /*
- * If unconfigured, make stash never expire
- */
- if (!strcmp(ref, "refs/stash")) {
- if (!(cb->explicit_expiry & EXPIRE_TOTAL))
- cb->expire_total = 0;
- if (!(cb->explicit_expiry & EXPIRE_UNREACH))
- cb->expire_unreachable = 0;
- return;
- }
-
- /* Nothing matched -- use the default value */
- if (!(cb->explicit_expiry & EXPIRE_TOTAL))
- cb->expire_total = default_reflog_expire;
- if (!(cb->explicit_expiry & EXPIRE_UNREACH))
- cb->expire_unreachable = default_reflog_expire_unreachable;
-}
-
static int expire_unreachable_callback(const struct option *opt,
const char *arg,
int unset)
{
- struct cmd_reflog_expire_cb *cmd = opt->value;
+ struct reflog_expire_options *opts = opt->value;
BUG_ON_OPT_NEG(unset);
- if (parse_expiry_date(arg, &cmd->expire_unreachable))
+ if (parse_expiry_date(arg, &opts->expire_unreachable))
die(_("invalid timestamp '%s' given to '--%s'"),
arg, opt->long_name);
- cmd->explicit_expiry |= EXPIRE_UNREACH;
+ opts->explicit_expiry |= REFLOG_EXPIRE_UNREACH;
return 0;
}
@@ -223,15 +117,15 @@ static int expire_total_callback(const struct option *opt,
const char *arg,
int unset)
{
- struct cmd_reflog_expire_cb *cmd = opt->value;
+ struct reflog_expire_options *opts = opt->value;
BUG_ON_OPT_NEG(unset);
- if (parse_expiry_date(arg, &cmd->expire_total))
+ if (parse_expiry_date(arg, &opts->expire_total))
die(_("invalid timestamp '%s' given to '--%s'"),
arg, opt->long_name);
- cmd->explicit_expiry |= EXPIRE_TOTAL;
+ opts->explicit_expiry |= REFLOG_EXPIRE_TOTAL;
return 0;
}
@@ -276,8 +170,8 @@ static int cmd_reflog_list(int argc, const char **argv, const char *prefix,
static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
struct repository *repo UNUSED)
{
- struct cmd_reflog_expire_cb cmd = { 0 };
timestamp_t now = time(NULL);
+ struct reflog_expire_options opts = REFLOG_EXPIRE_OPTIONS_INIT(now);
int i, status, do_all, single_worktree = 0;
unsigned int flags = 0;
int verbose = 0;
@@ -292,15 +186,15 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
N_("update the reference to the value of the top reflog entry"),
EXPIRE_REFLOGS_UPDATE_REF),
OPT_BOOL(0, "verbose", &verbose, N_("print extra information on screen")),
- OPT_CALLBACK_F(0, "expire", &cmd, N_("timestamp"),
+ OPT_CALLBACK_F(0, "expire", &opts, N_("timestamp"),
N_("prune entries older than the specified time"),
PARSE_OPT_NONEG,
expire_total_callback),
- OPT_CALLBACK_F(0, "expire-unreachable", &cmd, N_("timestamp"),
+ OPT_CALLBACK_F(0, "expire-unreachable", &opts, N_("timestamp"),
N_("prune entries older than <time> that are not reachable from the current tip of the branch"),
PARSE_OPT_NONEG,
expire_unreachable_callback),
- OPT_BOOL(0, "stale-fix", &cmd.stalefix,
+ OPT_BOOL(0, "stale-fix", &opts.stalefix,
N_("prune any reflog entries that point to broken commits")),
OPT_BOOL(0, "all", &do_all, N_("process the reflogs of all references")),
OPT_BOOL(0, "single-worktree", &single_worktree,
@@ -308,17 +202,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
OPT_END()
};
- default_reflog_expire_unreachable = now - 30 * 24 * 3600;
- default_reflog_expire = now - 90 * 24 * 3600;
- git_config(reflog_expire_config, NULL);
+ git_config(reflog_expire_config, &opts);
save_commit_buffer = 0;
do_all = status = 0;
- cmd.explicit_expiry = 0;
- cmd.expire_total = default_reflog_expire;
- cmd.expire_unreachable = default_reflog_expire_unreachable;
-
argc = parse_options(argc, argv, prefix, options, reflog_expire_usage, 0);
if (verbose)
@@ -329,7 +217,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
* even in older repository. We cannot trust what's reachable
* from reflog if the repository was pruned with older git.
*/
- if (cmd.stalefix) {
+ if (opts.stalefix) {
struct rev_info revs;
repo_init_revisions(the_repository, &revs, prefix);
@@ -363,11 +251,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
for_each_string_list_item(item, &collected.reflogs) {
struct expire_reflog_policy_cb cb = {
- .cmd = cmd,
+ .opts = opts,
.dry_run = !!(flags & EXPIRE_REFLOGS_DRY_RUN),
};
- set_reflog_expiry_param(&cb.cmd, item->string);
+ reflog_expire_options_set_refname(&cb.opts, item->string);
status |= refs_reflog_expire(get_main_ref_store(the_repository),
item->string, flags,
reflog_expiry_prepare,
@@ -380,13 +268,13 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix,
for (i = 0; i < argc; i++) {
char *ref;
- struct expire_reflog_policy_cb cb = { .cmd = cmd };
+ struct expire_reflog_policy_cb cb = { .opts = opts };
if (!repo_dwim_log(the_repository, argv[i], strlen(argv[i]), NULL, &ref)) {
- status |= error(_("%s points nowhere!"), argv[i]);
+ status |= error(_("reflog could not be found: '%s'"), argv[i]);
continue;
}
- set_reflog_expiry_param(&cb.cmd, ref);
+ reflog_expire_options_set_refname(&cb.opts, ref);
status |= refs_reflog_expire(get_main_ref_store(the_repository),
ref, flags,
reflog_expiry_prepare,
@@ -449,10 +337,64 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix,
refname);
}
+static int cmd_reflog_drop(int argc, const char **argv, const char *prefix,
+ struct repository *repo)
+{
+ int ret = 0, do_all = 0, single_worktree = 0;
+ const struct option options[] = {
+ OPT_BOOL(0, "all", &do_all, N_("drop the reflogs of all references")),
+ OPT_BOOL(0, "single-worktree", &single_worktree,
+ N_("drop reflogs from the current worktree only")),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, prefix, options, reflog_drop_usage, 0);
+
+ if (argc && do_all)
+ usage(_("references specified along with --all"));
+
+ if (do_all) {
+ struct worktree_reflogs collected = {
+ .reflogs = STRING_LIST_INIT_DUP,
+ };
+ struct string_list_item *item;
+ struct worktree **worktrees, **p;
+
+ worktrees = get_worktrees();
+ for (p = worktrees; *p; p++) {
+ if (single_worktree && !(*p)->is_current)
+ continue;
+ collected.worktree = *p;
+ refs_for_each_reflog(get_worktree_ref_store(*p),
+ collect_reflog, &collected);
+ }
+ free_worktrees(worktrees);
+
+ for_each_string_list_item(item, &collected.reflogs)
+ ret |= refs_delete_reflog(get_main_ref_store(repo),
+ item->string);
+ string_list_clear(&collected.reflogs, 0);
+
+ return ret;
+ }
+
+ for (int i = 0; i < argc; i++) {
+ char *ref;
+ if (!repo_dwim_log(repo, argv[i], strlen(argv[i]), NULL, &ref)) {
+ ret |= error(_("reflog could not be found: '%s'"), argv[i]);
+ continue;
+ }
+
+ ret |= refs_delete_reflog(get_main_ref_store(repo), ref);
+ free(ref);
+ }
+
+ return ret;
+}
+
/*
* main "reflog"
*/
-
int cmd_reflog(int argc,
const char **argv,
const char *prefix,
@@ -465,6 +407,7 @@ int cmd_reflog(int argc,
OPT_SUBCOMMAND("expire", &fn, cmd_reflog_expire),
OPT_SUBCOMMAND("delete", &fn, cmd_reflog_delete),
OPT_SUBCOMMAND("exists", &fn, cmd_reflog_exists),
+ OPT_SUBCOMMAND("drop", &fn, cmd_reflog_drop),
OPT_END()
};
diff --git a/builtin/refs.c b/builtin/refs.c
index 44d592a94c..998d2a2c1c 100644
--- a/builtin/refs.c
+++ b/builtin/refs.c
@@ -91,7 +91,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix,
git_config(git_fsck_config, &fsck_refs_options);
prepare_repo_settings(the_repository);
- worktrees = get_worktrees();
+ worktrees = get_worktrees_without_reading_head();
for (size_t i = 0; worktrees[i]; i++)
ret |= refs_fsck(get_worktree_ref_store(worktrees[i]),
&fsck_refs_options, worktrees[i]);
diff --git a/builtin/remote.c b/builtin/remote.c
index 1b7aad8838..0d6755bcb7 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -14,7 +14,7 @@
#include "rebase.h"
#include "refs.h"
#include "refspec.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "strvec.h"
#include "commit-reach.h"
#include "progress.h"
@@ -454,7 +454,8 @@ static int get_push_ref_states(const struct ref *remote_refs,
info->status = PUSH_STATUS_UPTODATE;
else if (is_null_oid(&ref->old_oid))
info->status = PUSH_STATUS_CREATE;
- else if (repo_has_object_file(the_repository, &ref->old_oid) &&
+ else if (has_object(the_repository, &ref->old_oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) &&
ref_newer(&ref->new_oid, &ref->old_oid))
info->status = PUSH_STATUS_FASTFORWARD;
else
@@ -511,7 +512,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
- fetch_map, 1);
+ fetch_map, REMOTE_GUESS_HEAD_ALL);
for (ref = matches; ref; ref = ref->next)
string_list_append(&states->heads, abbrev_branch(ref->name));
diff --git a/builtin/repack.c b/builtin/repack.c
index 75e3752353..5ddc6e7f95 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -17,7 +17,7 @@
#include "midx.h"
#include "packfile.h"
#include "prune-packed.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "promisor-remote.h"
#include "shallow.h"
#include "pack.h"
@@ -43,7 +43,7 @@ static char *packdir, *packtmp_name, *packtmp;
static const char *const git_repack_usage[] = {
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>]"),
+ "[--write-midx] [--name-hash-version=<n>] [--path-walk]"),
NULL
};
@@ -63,6 +63,7 @@ struct pack_objects_args {
int quiet;
int local;
int name_hash_version;
+ int path_walk;
struct list_objects_filter_options filter_options;
};
@@ -313,6 +314,8 @@ static void prepare_pack_objects(struct child_process *cmd,
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->path_walk)
+ strvec_pushf(&cmd->args, "--path-walk");
if (args->local)
strvec_push(&cmd->args, "--local");
if (args->quiet)
@@ -1022,29 +1025,13 @@ static int write_filtered_pack(const struct pack_objects_args *args,
return finish_pack_objects_cmd(&cmd, names, local);
}
-static int existing_cruft_pack_cmp(const void *va, const void *vb)
+static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size,
+ struct existing_packs *existing)
{
- struct packed_git *a = *(struct packed_git **)va;
- struct packed_git *b = *(struct packed_git **)vb;
-
- if (a->pack_size < b->pack_size)
- return -1;
- if (a->pack_size > b->pack_size)
- return 1;
- return 0;
-}
-
-static void collapse_small_cruft_packs(FILE *in, size_t max_size,
- struct existing_packs *existing)
-{
- struct packed_git **existing_cruft, *p;
+ struct packed_git *p;
struct strbuf buf = STRBUF_INIT;
- size_t total_size = 0;
- size_t existing_cruft_nr = 0;
size_t i;
- ALLOC_ARRAY(existing_cruft, existing->cruft_packs.nr);
-
for (p = get_all_packs(the_repository); p; p = p->next) {
if (!(p->is_cruft && p->pack_local))
continue;
@@ -1056,24 +1043,7 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size,
if (!string_list_has_string(&existing->cruft_packs, buf.buf))
continue;
- if (existing_cruft_nr >= existing->cruft_packs.nr)
- BUG("too many cruft packs (found %"PRIuMAX", but knew "
- "of %"PRIuMAX")",
- (uintmax_t)existing_cruft_nr + 1,
- (uintmax_t)existing->cruft_packs.nr);
- existing_cruft[existing_cruft_nr++] = p;
- }
-
- QSORT(existing_cruft, existing_cruft_nr, existing_cruft_pack_cmp);
-
- for (i = 0; i < existing_cruft_nr; i++) {
- size_t proposed;
-
- p = existing_cruft[i];
- proposed = st_add(total_size, p->pack_size);
-
- if (proposed <= max_size) {
- total_size = proposed;
+ if (p->pack_size < combine_cruft_below_size) {
fprintf(in, "-%s\n", pack_basename(p));
} else {
retain_cruft_pack(existing, p);
@@ -1086,13 +1056,13 @@ static void collapse_small_cruft_packs(FILE *in, size_t max_size,
existing->non_kept_packs.items[i].string);
strbuf_release(&buf);
- free(existing_cruft);
}
static int write_cruft_pack(const struct pack_objects_args *args,
const char *destination,
const char *pack_prefix,
const char *cruft_expiration,
+ unsigned long combine_cruft_below_size,
struct string_list *names,
struct existing_packs *existing)
{
@@ -1135,8 +1105,9 @@ static int write_cruft_pack(const struct pack_objects_args *args,
in = xfdopen(cmd.in, "w");
for_each_string_list_item(item, names)
fprintf(in, "%s-%s.pack\n", pack_prefix, item->string);
- if (args->max_pack_size && !cruft_expiration) {
- collapse_small_cruft_packs(in, args->max_pack_size, existing);
+ if (combine_cruft_below_size && !cruft_expiration) {
+ combine_small_cruft_packs(in, combine_cruft_below_size,
+ existing);
} else {
for_each_string_list_item(item, &existing->non_kept_packs)
fprintf(in, "-%s.pack\n", item->string);
@@ -1190,6 +1161,7 @@ int cmd_repack(int argc,
const char *opt_window_memory = NULL;
const char *opt_depth = NULL;
const char *opt_threads = NULL;
+ unsigned long combine_cruft_below_size = 0ul;
struct option builtin_repack_options[] = {
OPT_BIT('a', NULL, &pack_everything,
@@ -1202,8 +1174,11 @@ int cmd_repack(int argc,
PACK_CRUFT),
OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"),
N_("with --cruft, expire objects older than this")),
- OPT_MAGNITUDE(0, "max-cruft-size", &cruft_po_args.max_pack_size,
- N_("with --cruft, limit the size of new cruft packs")),
+ OPT_UNSIGNED(0, "combine-cruft-below-size",
+ &combine_cruft_below_size,
+ N_("with --cruft, only repack cruft packs smaller than this")),
+ OPT_UNSIGNED(0, "max-cruft-size", &cruft_po_args.max_pack_size,
+ N_("with --cruft, limit the size of new cruft packs")),
OPT_BOOL('d', NULL, &delete_redundant,
N_("remove redundant packs, and run git-prune-packed")),
OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
@@ -1212,6 +1187,8 @@ int cmd_repack(int argc,
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_BOOL(0, "path-walk", &po_args.path_walk,
+ N_("pass --path-walk to git-pack-objects")),
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")),
@@ -1233,8 +1210,8 @@ int cmd_repack(int argc,
N_("limits the maximum delta depth")),
OPT_STRING(0, "threads", &opt_threads, N_("n"),
N_("limits the maximum number of threads")),
- OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size,
- N_("maximum size of each packfile")),
+ OPT_UNSIGNED(0, "max-pack-size", &po_args.max_pack_size,
+ N_("maximum size of each packfile")),
OPT_PARSE_LIST_OBJECTS_FILTER(&po_args.filter_options),
OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
N_("repack objects in packs marked with .keep")),
@@ -1445,7 +1422,8 @@ int cmd_repack(int argc,
cruft_po_args.quiet = po_args.quiet;
ret = write_cruft_pack(&cruft_po_args, packtmp, pack_prefix,
- cruft_expiration, &names,
+ cruft_expiration,
+ combine_cruft_below_size, &names,
&existing);
if (ret)
goto cleanup;
@@ -1472,10 +1450,17 @@ int cmd_repack(int argc,
* generate an empty pack (since every object not in the
* cruft pack generated above will have an mtime older
* than the expiration).
+ *
+ * Pretend we don't have a `--combine-cruft-below-size`
+ * argument, since we're not selectively combining
+ * anything based on size to generate the limbo cruft
+ * pack, but rather removing all cruft packs from the
+ * main repository regardless of size.
*/
ret = write_cruft_pack(&cruft_po_args, expire_to,
pack_prefix,
NULL,
+ 0ul,
&names,
&existing);
if (ret)
diff --git a/builtin/replace.c b/builtin/replace.c
index 15ec0922ce..48c7c6a2d5 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -19,7 +19,7 @@
#include "run-command.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "replace-object.h"
#include "tag.h"
#include "wildmatch.h"
@@ -305,7 +305,7 @@ static int import_object(struct object_id *oid, enum object_type type,
strbuf_release(&result);
} else {
struct stat st;
- int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
+ int flags = INDEX_FORMAT_CHECK | INDEX_WRITE_OBJECT;
if (fstat(fd, &st) < 0) {
error_errno(_("unable to fstat %s"), filename);
diff --git a/builtin/replay.c b/builtin/replay.c
index 032c172b65..225cef0880 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -20,21 +20,22 @@
#include <oidset.h>
#include <tree.h>
-static const char *short_commit_name(struct commit *commit)
+static const char *short_commit_name(struct repository *repo,
+ struct commit *commit)
{
- return repo_find_unique_abbrev(the_repository, &commit->object.oid,
+ return repo_find_unique_abbrev(repo, &commit->object.oid,
DEFAULT_ABBREV);
}
-static struct commit *peel_committish(const char *name)
+static struct commit *peel_committish(struct repository *repo, const char *name)
{
struct object *obj;
struct object_id oid;
- if (repo_get_oid(the_repository, name, &oid))
+ if (repo_get_oid(repo, name, &oid))
return NULL;
- obj = parse_object(the_repository, &oid);
- return (struct commit *)repo_peel_to_type(the_repository, name, 0, obj,
+ obj = parse_object(repo, &oid);
+ return (struct commit *)repo_peel_to_type(repo, name, 0, obj,
OBJ_COMMIT);
}
@@ -50,7 +51,8 @@ static char *get_author(const char *message)
return NULL;
}
-static struct commit *create_commit(struct tree *tree,
+static struct commit *create_commit(struct repository *repo,
+ struct tree *tree,
struct commit *based_on,
struct commit *parent)
{
@@ -62,7 +64,7 @@ static struct commit *create_commit(struct tree *tree,
struct commit_extra_header *extra = NULL;
struct strbuf msg = STRBUF_INIT;
const char *out_enc = get_commit_output_encoding();
- const char *message = repo_logmsg_reencode(the_repository, based_on,
+ const char *message = repo_logmsg_reencode(repo, based_on,
NULL, out_enc);
const char *orig_message = NULL;
const char *exclude_gpgsig[] = { "gpgsig", NULL };
@@ -79,7 +81,7 @@ static struct commit *create_commit(struct tree *tree,
goto out;
}
- obj = parse_object(the_repository, &ret);
+ obj = parse_object(repo, &ret);
out:
free_commit_extra_headers(extra);
@@ -97,7 +99,8 @@ struct ref_info {
int negative_refexprs;
};
-static void get_ref_information(struct rev_cmdline_info *cmd_info,
+static void get_ref_information(struct repository *repo,
+ struct rev_cmdline_info *cmd_info,
struct ref_info *ref_info)
{
int i;
@@ -132,14 +135,14 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info,
if (*refexpr == '^')
refexpr++;
- if (repo_dwim_ref(the_repository, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1)
+ if (repo_dwim_ref(repo, refexpr, strlen(refexpr), &oid, &fullname, 0) != 1)
can_uniquely_dwim = 0;
if (e->flags & BOTTOM) {
if (can_uniquely_dwim)
strset_add(&ref_info->negative_refs, fullname);
if (!ref_info->negative_refexprs)
- ref_info->onto = lookup_commit_reference_gently(the_repository,
+ ref_info->onto = lookup_commit_reference_gently(repo,
&e->item->oid, 1);
ref_info->negative_refexprs++;
} else {
@@ -152,7 +155,8 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info,
}
}
-static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
+static void determine_replay_mode(struct repository *repo,
+ struct rev_cmdline_info *cmd_info,
const char *onto_name,
char **advance_name,
struct commit **onto,
@@ -160,14 +164,14 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
{
struct ref_info rinfo;
- get_ref_information(cmd_info, &rinfo);
+ get_ref_information(repo, cmd_info, &rinfo);
if (!rinfo.positive_refexprs)
die(_("need some commits to replay"));
die_for_incompatible_opt2(!!onto_name, "--onto",
!!*advance_name, "--advance");
if (onto_name) {
- *onto = peel_committish(onto_name);
+ *onto = peel_committish(repo, onto_name);
if (rinfo.positive_refexprs <
strset_get_size(&rinfo.positive_refs))
die(_("all positive revisions given must be references"));
@@ -175,8 +179,8 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
struct object_id oid;
char *fullname = NULL;
- *onto = peel_committish(*advance_name);
- if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name),
+ *onto = peel_committish(repo, *advance_name);
+ if (repo_dwim_ref(repo, *advance_name, strlen(*advance_name),
&oid, &fullname, 0) == 1) {
free(*advance_name);
*advance_name = fullname;
@@ -245,7 +249,8 @@ static struct commit *mapped_commit(kh_oid_map_t *replayed_commits,
return kh_value(replayed_commits, pos);
}
-static struct commit *pick_regular_commit(struct commit *pickme,
+static struct commit *pick_regular_commit(struct repository *repo,
+ struct commit *pickme,
kh_oid_map_t *replayed_commits,
struct commit *onto,
struct merge_options *merge_opt,
@@ -257,12 +262,12 @@ static struct commit *pick_regular_commit(struct commit *pickme,
base = pickme->parents->item;
replayed_base = mapped_commit(replayed_commits, base, onto);
- result->tree = repo_get_commit_tree(the_repository, replayed_base);
- pickme_tree = repo_get_commit_tree(the_repository, pickme);
- base_tree = repo_get_commit_tree(the_repository, base);
+ result->tree = repo_get_commit_tree(repo, replayed_base);
+ pickme_tree = repo_get_commit_tree(repo, pickme);
+ base_tree = repo_get_commit_tree(repo, base);
- merge_opt->branch1 = short_commit_name(replayed_base);
- merge_opt->branch2 = short_commit_name(pickme);
+ merge_opt->branch1 = short_commit_name(repo, replayed_base);
+ merge_opt->branch2 = short_commit_name(repo, pickme);
merge_opt->ancestor = xstrfmt("parent of %s", merge_opt->branch2);
merge_incore_nonrecursive(merge_opt,
@@ -275,13 +280,13 @@ static struct commit *pick_regular_commit(struct commit *pickme,
merge_opt->ancestor = NULL;
if (!result->clean)
return NULL;
- return create_commit(result->tree, pickme, replayed_base);
+ return create_commit(repo, result->tree, pickme, replayed_base);
}
int cmd_replay(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
const char *advance_name_opt = NULL;
char *advance_name = NULL;
@@ -329,7 +334,7 @@ int cmd_replay(int argc,
"--advance", "--contained");
advance_name = xstrdup_or_null(advance_name_opt);
- repo_init_revisions(the_repository, &revs, prefix);
+ repo_init_revisions(repo, &revs, prefix);
/*
* Set desired values for rev walking options here. If they
@@ -380,7 +385,7 @@ int cmd_replay(int argc,
revs.simplify_history = 0;
}
- determine_replay_mode(&revs.cmdline, onto_name, &advance_name,
+ determine_replay_mode(repo, &revs.cmdline, onto_name, &advance_name,
&onto, &update_refs);
if (!onto) /* FIXME: Should handle replaying down to root commit */
@@ -391,7 +396,7 @@ int cmd_replay(int argc,
goto cleanup;
}
- init_basic_merge_options(&merge_opt, the_repository);
+ init_basic_merge_options(&merge_opt, repo);
memset(&result, 0, sizeof(result));
merge_opt.show_rename_progress = 0;
last_commit = onto;
@@ -406,8 +411,8 @@ int cmd_replay(int argc,
if (commit->parents->next)
die(_("replaying merge commits is not supported yet!"));
- last_commit = pick_regular_commit(commit, replayed_commits, onto,
- &merge_opt, &result);
+ last_commit = pick_regular_commit(repo, commit, replayed_commits,
+ onto, &merge_opt, &result);
if (!last_commit)
break;
diff --git a/builtin/reset.c b/builtin/reset.c
index 73b4537a9a..dc50ffc1ac 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -420,6 +420,9 @@ int cmd_reset(int argc,
oidcpy(&oid, &tree->object.oid);
}
+ prepare_repo_settings(the_repository);
+ the_repository->settings.command_requires_full_index = 0;
+
if (patch_mode) {
if (reset_type != NONE)
die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
@@ -457,9 +460,6 @@ int cmd_reset(int argc,
if (intent_to_add && reset_type != MIXED)
die(_("the option '%s' requires '%s'"), "-N", "--mixed");
- prepare_repo_settings(the_repository);
- the_repository->settings.command_requires_full_index = 0;
-
if (repo_read_index(the_repository) < 0)
die(_("index file corrupt"));
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index bb26bee0d4..0984b607bf 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -14,8 +14,9 @@
#include "object.h"
#include "object-name.h"
#include "object-file.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "pack-bitmap.h"
+#include "parse-options.h"
#include "log-tree.h"
#include "graph.h"
#include "bisect.h"
@@ -64,6 +65,7 @@ static const char rev_list_usage[] =
" --abbrev-commit\n"
" --left-right\n"
" --count\n"
+" -z\n"
" special purpose:\n"
" --bisect\n"
" --bisect-vars\n"
@@ -96,6 +98,9 @@ static int arg_show_object_names = 1;
#define DEFAULT_OIDSET_SIZE (16*1024)
+static char line_term = '\n';
+static char info_term = ' ';
+
static int show_disk_usage;
static off_t total_disk_usage;
static int human_readable;
@@ -131,24 +136,37 @@ static void print_missing_object(struct missing_objects_map_entry *entry,
{
struct strbuf sb = STRBUF_INIT;
+ if (line_term)
+ printf("?%s", oid_to_hex(&entry->entry.oid));
+ else
+ printf("%s%cmissing=yes", oid_to_hex(&entry->entry.oid),
+ info_term);
+
if (!print_missing_info) {
- printf("?%s\n", oid_to_hex(&entry->entry.oid));
+ putchar(line_term);
return;
}
if (entry->path && *entry->path) {
- struct strbuf path = STRBUF_INIT;
+ strbuf_addf(&sb, "%cpath=", info_term);
- strbuf_addstr(&sb, " path=");
- quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
- strbuf_addbuf(&sb, &path);
+ if (line_term) {
+ struct strbuf path = STRBUF_INIT;
- strbuf_release(&path);
+ quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
+ strbuf_addbuf(&sb, &path);
+
+ strbuf_release(&path);
+ } else {
+ strbuf_addstr(&sb, entry->path);
+ }
}
if (entry->type)
- strbuf_addf(&sb, " type=%s", type_name(entry->type));
+ strbuf_addf(&sb, "%ctype=%s", info_term, type_name(entry->type));
+
+ fwrite(sb.buf, sizeof(char), sb.len, stdout);
+ putchar(line_term);
- printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf);
strbuf_release(&sb);
}
@@ -235,13 +253,18 @@ static void show_commit(struct commit *commit, void *data)
fputs(info->header_prefix, stdout);
if (revs->include_header) {
- if (!revs->graph)
+ if (!revs->graph && line_term)
fputs(get_revision_mark(revs, commit), stdout);
if (revs->abbrev_commit && revs->abbrev)
fputs(repo_find_unique_abbrev(the_repository, &commit->object.oid, revs->abbrev),
stdout);
else
fputs(oid_to_hex(&commit->object.oid), stdout);
+
+ if (!line_term) {
+ if (commit->object.flags & BOUNDARY)
+ printf("%cboundary=yes", info_term);
+ }
}
if (revs->print_parents) {
struct commit_list *parents = commit->parents;
@@ -263,7 +286,7 @@ static void show_commit(struct commit *commit, void *data)
if (revs->commit_format == CMIT_FMT_ONELINE)
putchar(' ');
else if (revs->include_header)
- putchar('\n');
+ putchar(line_term);
if (revs->verbose_header) {
struct strbuf buf = STRBUF_INIT;
@@ -357,10 +380,19 @@ static void show_object(struct object *obj, const char *name, void *cb_data)
return;
}
- if (arg_show_object_names)
- show_object_with_name(stdout, obj, name);
- else
- printf("%s\n", oid_to_hex(&obj->oid));
+ printf("%s", oid_to_hex(&obj->oid));
+
+ if (arg_show_object_names) {
+ if (line_term) {
+ putchar(info_term);
+ for (const char *p = name; *p && *p != '\n'; p++)
+ putchar(*p);
+ } else if (*name) {
+ printf("%cpath=%s", info_term, name);
+ }
+ }
+
+ putchar(line_term);
}
static void show_edge(struct commit *commit)
@@ -429,7 +461,8 @@ static int show_object_fast(
int exclude UNUSED,
uint32_t name_hash UNUSED,
struct packed_git *found_pack UNUSED,
- off_t found_offset UNUSED)
+ off_t found_offset UNUSED,
+ void *payload UNUSED)
{
fprintf(stdout, "%s\n", oid_to_hex(oid));
return 1;
@@ -634,19 +667,18 @@ int cmd_rev_list(int argc,
if (!strcmp(arg, "--exclude-promisor-objects")) {
fetch_if_missing = 0;
revs.exclude_promisor_objects = 1;
- break;
- }
- }
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
- if (skip_prefix(arg, "--missing=", &arg)) {
- if (revs.exclude_promisor_objects)
- die(_("options '%s' and '%s' cannot be used together"), "--exclude-promisor-objects", "--missing");
- if (parse_missing_action_value(arg))
- break;
+ } else if (skip_prefix(arg, "--missing=", &arg)) {
+ parse_missing_action_value(arg);
+ } else if (!strcmp(arg, "-z")) {
+ line_term = '\0';
+ info_term = '\0';
}
}
+ die_for_incompatible_opt2(revs.exclude_promisor_objects,
+ "--exclude_promisor_objects",
+ arg_missing_action, "--missing");
+
if (arg_missing_action)
revs.do_not_die_on_missing_objects = 1;
@@ -755,6 +787,20 @@ int cmd_rev_list(int argc,
usage(rev_list_usage);
}
+
+ /*
+ * Reject options currently incompatible with -z. For some options, this
+ * is not an inherent limitation and support may be implemented in the
+ * future.
+ */
+ if (!line_term) {
+ if (revs.graph || revs.verbose_header || show_disk_usage ||
+ info.show_timestamp || info.header_prefix || bisect_list ||
+ use_bitmap_index || revs.edge_hint || revs.left_right ||
+ revs.cherry_mark)
+ die(_("-z option used with unsupported option"));
+ }
+
if (revs.commit_format != CMIT_FMT_USERFORMAT)
revs.include_header = 1;
if (revs.commit_format != CMIT_FMT_UNSPECIFIED) {
@@ -878,7 +924,7 @@ int cmd_rev_list(int argc,
free((void *)entry->path);
}
- oidmap_free(&missing_objects, true);
+ oidmap_clear(&missing_objects, true);
}
stop_progress(&progress);
diff --git a/builtin/revert.c b/builtin/revert.c
index aca6c293cd..e07c2217fe 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -132,8 +132,16 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")),
OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
N_("option for merge strategy")),
- { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
- N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ {
+ .type = OPTION_STRING,
+ .short_name = 'S',
+ .long_name = "gpg-sign",
+ .value = &gpg_sign,
+ .argh = N_("key-id"),
+ .help = N_("GPG sign commit"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = (intptr_t) "",
+ },
OPT_END()
};
struct option *options = base_options;
@@ -252,8 +260,6 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
free(opts->strategy);
opts->strategy = xstrdup_or_null(strategy);
}
- if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
- opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
free(options);
if (cmd == 'q') {
diff --git a/builtin/rm.c b/builtin/rm.c
index 12ae086a55..a6565a69cf 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -5,7 +5,6 @@
*/
#define USE_THE_REPOSITORY_VARIABLE
-#define DISABLE_SIGN_COMPARE_WARNINGS
#include "builtin.h"
#include "advice.h"
@@ -40,14 +39,12 @@ static struct {
} *entry;
} list;
-static int get_ours_cache_pos(const char *path, int pos)
+static int get_ours_cache_pos(const char *path, unsigned int pos)
{
- int i = -pos - 1;
-
- while ((i < the_repository->index->cache_nr) && !strcmp(the_repository->index->cache[i]->name, path)) {
- if (ce_stage(the_repository->index->cache[i]) == 2)
- return i;
- i++;
+ while ((pos < the_repository->index->cache_nr) && !strcmp(the_repository->index->cache[pos]->name, path)) {
+ if (ce_stage(the_repository->index->cache[pos]) == 2)
+ return pos;
+ pos++;
}
return -1;
}
@@ -58,7 +55,7 @@ static void print_error_files(struct string_list *files_list,
int *errs)
{
if (files_list->nr) {
- int i;
+ unsigned int i;
struct strbuf err_msg = STRBUF_INIT;
strbuf_addstr(&err_msg, main_msg);
@@ -83,7 +80,7 @@ static void submodules_absorb_gitdir_if_needed(void)
pos = index_name_pos(the_repository->index, name, strlen(name));
if (pos < 0) {
- pos = get_ours_cache_pos(name, pos);
+ pos = get_ours_cache_pos(name, -pos - 1);
if (pos < 0)
continue;
}
@@ -131,7 +128,7 @@ static int check_local_mod(struct object_id *head, int index_only)
* Skip unmerged entries except for populated submodules
* that could lose history when removed.
*/
- pos = get_ours_cache_pos(name, pos);
+ pos = get_ours_cache_pos(name, -pos - 1);
if (pos < 0)
continue;
@@ -314,7 +311,7 @@ int cmd_rm(int argc,
if (pathspec_needs_expanded_index(the_repository->index, &pathspec))
ensure_full_index(the_repository->index);
- for (i = 0; i < the_repository->index->cache_nr; i++) {
+ for (unsigned int i = 0; i < the_repository->index->cache_nr; i++) {
const struct cache_entry *ce = the_repository->index->cache[i];
if (!include_sparse &&
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 8d461008e2..c6e0e9d051 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "hex.h"
@@ -151,7 +150,7 @@ static int send_pack_config(const char *k, const char *v,
int cmd_send_pack(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
struct refspec rs = REFSPEC_INIT_PUSH;
const char *remote_name = NULL;
@@ -212,7 +211,7 @@ int cmd_send_pack(int argc,
OPT_END()
};
- git_config(send_pack_config, NULL);
+ repo_config(repo, send_pack_config, NULL);
argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
if (argc > 0) {
dest = argv[0];
@@ -317,7 +316,7 @@ int cmd_send_pack(int argc,
set_ref_status_for_push(remote_refs, args.send_mirror,
args.force_update);
- ret = send_pack(the_repository, &args, fd, conn, remote_refs, &extra_have);
+ ret = send_pack(repo, &args, fd, conn, remote_refs, &extra_have);
if (helper_status)
print_helper_status(remote_refs);
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index fce6b404e9..525b231d87 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -19,7 +19,7 @@
#include "date.h"
#include "wildmatch.h"
-static const char* show_branch_usage[] = {
+static const char*const show_branch_usage[] = {
N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
" [--current] [--color[=<when>] | --no-color] [--sparse]\n"
" [--more=<n> | --list | --independent | --merge-base]\n"
@@ -667,9 +667,16 @@ int cmd_show_branch(int ac,
N_("show remote-tracking branches")),
OPT__COLOR(&showbranch_use_color,
N_("color '*!+-' corresponding to the branch")),
- { OPTION_INTEGER, 0, "more", &extra, N_("n"),
- N_("show <n> more commits after the common ancestor"),
- PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
+ {
+ .type = OPTION_INTEGER,
+ .long_name = "more",
+ .value = &extra,
+ .precision = sizeof(extra),
+ .argh = N_("n"),
+ .help = N_("show <n> more commits after the common ancestor"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = 1,
+ },
OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
OPT_BOOL(0, "current", &with_current_branch,
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 285cd3e433..623a52a45f 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -5,7 +5,7 @@
#include "hex.h"
#include "refs/refs-internal.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "object.h"
#include "string-list.h"
#include "parse-options.h"
@@ -35,7 +35,8 @@ static void show_one(const struct show_one_options *opts,
const char *hex;
struct object_id peeled;
- if (!repo_has_object_file(the_repository, oid))
+ if (!has_object(the_repository, oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
die("git show-ref: bad ref %s (%s)", refname,
oid_to_hex(oid));
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 14dcace5f8..1bf01591b2 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -9,6 +9,7 @@
#include "object-file.h"
#include "object-name.h"
#include "parse-options.h"
+#include "path.h"
#include "pathspec.h"
#include "strbuf.h"
#include "string-list.h"
@@ -335,7 +336,7 @@ static int write_patterns_and_update(struct pattern_list *pl)
sparse_filename = get_sparse_checkout_filename();
- if (safe_create_leading_directories(sparse_filename))
+ if (safe_create_leading_directories(the_repository, sparse_filename))
die(_("failed to create directory for sparse-checkout file"));
hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR);
@@ -491,7 +492,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
FILE *fp;
/* assume we are in a fresh repo, but update the sparse-checkout file */
- if (safe_create_leading_directories(sparse_filename))
+ if (safe_create_leading_directories(the_repository, sparse_filename))
die(_("unable to create leading directories of %s"),
sparse_filename);
fp = xfopen(sparse_filename, "w");
diff --git a/builtin/stash.c b/builtin/stash.c
index dbaa999cf1..cfbd92852a 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -13,7 +13,6 @@
#include "lockfile.h"
#include "cache-tree.h"
#include "unpack-trees.h"
-#include "merge-recursive.h"
#include "merge-ort-wrappers.h"
#include "strvec.h"
#include "run-command.h"
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index c1a8029714..53da2116dd 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -28,7 +28,7 @@
#include "diff.h"
#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "advice.h"
#include "branch.h"
#include "list-objects-filter-options.h"
@@ -78,7 +78,7 @@ static int get_default_remote_submodule(const char *module_path, char **default_
int ret;
if (repo_submodule_init(&subrepo, the_repository, module_path,
- null_oid()) < 0)
+ null_oid(the_hash_algo)) < 0)
return die_message(_("could not get a repository handle for submodule '%s'"),
module_path);
ret = repo_get_default_remote(&subrepo, default_remote);
@@ -308,7 +308,7 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
displaypath = get_submodule_displaypath(path, info->prefix,
info->super_prefix);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub)
die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -468,7 +468,7 @@ static void init_submodule(const char *path, const char *prefix,
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub)
die(_("No url found for submodule path '%s' in .gitmodules"),
@@ -645,14 +645,14 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
if (validate_submodule_path(path) < 0)
exit(128);
- if (!submodule_from_path(the_repository, null_oid(), path))
+ if (!submodule_from_path(the_repository, null_oid(the_hash_algo), path))
die(_("no submodule mapping found in .gitmodules for path '%s'"),
path);
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
- print_status(flags, 'U', path, null_oid(), displaypath);
+ print_status(flags, 'U', path, null_oid(the_hash_algo), displaypath);
goto cleanup;
}
@@ -912,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,
struct strbuf errmsg = STRBUF_INIT;
int total_commits = -1;
- if (!info->cached && oideq(&p->oid_dst, null_oid())) {
+ if (!info->cached && oideq(&p->oid_dst, null_oid(the_hash_algo))) {
if (S_ISGITLINK(p->mod_dst)) {
struct ref_store *refs = repo_get_submodule_ref_store(the_repository,
p->sm_path);
@@ -1051,7 +1051,7 @@ static void prepare_submodule_summary(struct summary_cb *info,
if (info->for_status && p->status != 'A' &&
(sub = submodule_from_path(the_repository,
- null_oid(), p->sm_path))) {
+ null_oid(the_hash_algo), p->sm_path))) {
char *config_key = NULL;
const char *value;
int ignore_all = 0;
@@ -1259,7 +1259,7 @@ static void sync_submodule(const char *path, const char *prefix,
if (validate_submodule_path(path) < 0)
exit(128);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (sub && sub->url) {
if (starts_with_dot_dot_slash(sub->url) ||
@@ -1404,7 +1404,7 @@ static void deinit_submodule(const char *path, const char *prefix,
if (validate_submodule_path(path) < 0)
exit(128);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub || !sub->name)
goto cleanup;
@@ -1739,7 +1739,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
!is_empty_dir(clone_data_path))
die(_("directory not empty: '%s'"), clone_data_path);
- if (safe_create_leading_directories_const(sm_gitdir) < 0)
+ if (safe_create_leading_directories_const(the_repository, sm_gitdir) < 0)
die(_("could not create directory '%s'"), sm_gitdir);
prepare_possible_alternates(clone_data->name, reference);
@@ -1800,7 +1800,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
if (clone_data->require_init && !stat(clone_data_path, &st) &&
!is_empty_dir(clone_data_path))
die(_("directory not empty: '%s'"), clone_data_path);
- if (safe_create_leading_directories_const(clone_data_path) < 0)
+ if (safe_create_leading_directories_const(the_repository, clone_data_path) < 0)
die(_("could not create directory '%s'"), clone_data_path);
path = xstrfmt("%s/index", sm_gitdir);
unlink_or_warn(path);
@@ -1929,7 +1929,7 @@ static int determine_submodule_update_strategy(struct repository *r,
enum submodule_update_type update,
struct submodule_update_strategy *out)
{
- const struct submodule *sub = submodule_from_path(r, null_oid(), path);
+ const struct submodule *sub = submodule_from_path(r, null_oid(the_hash_algo), path);
char *key;
const char *val;
int ret;
@@ -2089,7 +2089,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
- sub = submodule_from_path(the_repository, null_oid(), ce->name);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), ce->name);
if (!sub) {
next_submodule_warn_missing(suc, out, displaypath);
@@ -2485,7 +2485,7 @@ static int remote_submodule_branch(const char *path, const char **branch)
char *key;
*branch = NULL;
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub)
return die_message(_("could not initialize submodule at path '%s'"),
path);
@@ -2531,7 +2531,7 @@ static int ensure_core_worktree(const char *path)
const char *cw;
struct repository subrepo;
- if (repo_submodule_init(&subrepo, the_repository, path, null_oid()))
+ if (repo_submodule_init(&subrepo, the_repository, path, null_oid(the_hash_algo)))
return die_message(_("could not get a repository handle for submodule '%s'"),
path);
@@ -2644,7 +2644,7 @@ static int update_submodule(struct update_data *update_data)
return ret;
if (update_data->just_cloned)
- oidcpy(&update_data->suboid, null_oid());
+ oidcpy(&update_data->suboid, null_oid(the_hash_algo));
else if (repo_resolve_gitlink_ref(the_repository, update_data->sm_path,
"HEAD", &update_data->suboid))
return die_message(_("Unable to find current revision in submodule path '%s'"),
@@ -2697,8 +2697,8 @@ static int update_submodule(struct update_data *update_data)
struct update_data next = *update_data;
next.prefix = NULL;
- oidcpy(&next.oid, null_oid());
- oidcpy(&next.suboid, null_oid());
+ oidcpy(&next.oid, null_oid(the_hash_algo));
+ oidcpy(&next.suboid, null_oid(the_hash_algo));
cp.dir = update_data->sm_path;
cp.git_cmd = 1;
@@ -3057,7 +3057,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix,
if (argc != 2 || !(path = argv[0]) || !(newurl = argv[1]))
usage_with_options(usage, options);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub)
die(_("no submodule mapping found in .gitmodules for path '%s'"),
@@ -3113,7 +3113,7 @@ static int module_set_branch(int argc, const char **argv, const char *prefix,
if (argc != 1 || !(path = argv[0]))
usage_with_options(usage, options);
- sub = submodule_from_path(the_repository, null_oid(), path);
+ sub = submodule_from_path(the_repository, null_oid(the_hash_algo), path);
if (!sub)
die(_("no submodule mapping found in .gitmodules for path '%s'"),
diff --git a/builtin/tag.c b/builtin/tag.c
index d3e0943b73..4742b27d16 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -17,8 +17,9 @@
#include "gettext.h"
#include "hex.h"
#include "refs.h"
+#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
#include "path.h"
#include "tag.h"
#include "parse-options.h"
@@ -172,7 +173,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
if (compat) {
const struct git_hash_algo *algo = the_repository->hash_algo;
- if (convert_object_file(&compat_buf, algo, compat,
+ if (convert_object_file(the_repository ,&compat_buf, algo, compat,
buffer->buf, buffer->len, OBJ_TAG, 1))
goto out;
if (sign_buffer(&compat_buf, &compat_sig, keyid))
@@ -479,9 +480,16 @@ int cmd_tag(int argc,
int edit_flag = 0;
struct option options[] = {
OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
- { OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"),
- N_("print <n> lines of each tag message"),
- PARSE_OPT_OPTARG, NULL, 1 },
+ {
+ .type = OPTION_INTEGER,
+ .short_name = 'n',
+ .value = &filter.lines,
+ .precision = sizeof(filter.lines),
+ .argh = N_("n"),
+ .help = N_("print <n> lines of each tag message"),
+ .flags = PARSE_OPT_OPTARG,
+ .defval = 1,
+ },
OPT_CMDMODE('d', "delete", &cmdmode, N_("delete tags"), 'd'),
OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
@@ -513,9 +521,14 @@ int cmd_tag(int argc,
N_("do not output a newline after empty formatted refs")),
OPT_REF_SORT(&sorting_options),
{
- OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
- N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
- parse_opt_object_name, (intptr_t) "HEAD"
+ .type = OPTION_CALLBACK,
+ .long_name = "points-at",
+ .value = &filter.points_at,
+ .argh = N_("object"),
+ .help = N_("print only tags of the object"),
+ .flags = PARSE_OPT_LASTARG_DEFAULT,
+ .callback = parse_opt_object_name,
+ .defval = (intptr_t) "HEAD",
},
OPT_STRING( 0 , "format", &format.format, N_("format"),
N_("format to use for the output")),
diff --git a/builtin/unpack-file.c b/builtin/unpack-file.c
index fb5fcbc40a..e33acfc4ee 100644
--- a/builtin/unpack-file.c
+++ b/builtin/unpack-file.c
@@ -2,8 +2,9 @@
#include "builtin.h"
#include "config.h"
#include "hex.h"
+#include "object-file.h"
#include "object-name.h"
-#include "object-store-ll.h"
+#include "object-store.h"
static char *create_temp_file(struct object_id *oid)
{
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 8383bcf404..e905d5f4e1 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -8,7 +8,8 @@
#include "gettext.h"
#include "git-zlib.h"
#include "hex.h"
-#include "object-store-ll.h"
+#include "object-file.h"
+#include "object-store.h"
#include "object.h"
#include "delta.h"
#include "pack.h"
@@ -448,7 +449,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
delta_data = get_data(delta_size);
if (!delta_data)
return;
- if (repo_has_object_file(the_repository, &base_oid))
+ if (has_object(the_repository, &base_oid,
+ HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR))
; /* Ok we have this one */
else if (resolve_against_held(nr, &base_oid,
delta_data, delta_size))
@@ -505,7 +507,7 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
* has not been resolved yet.
*/
oidclr(&obj_list[nr].oid, the_repository->hash_algo);
- add_delta_to_list(nr, null_oid(), base_offset,
+ add_delta_to_list(nr, null_oid(the_hash_algo), base_offset,
delta_data, delta_size);
return;
}
@@ -553,7 +555,8 @@ static void unpack_one(unsigned nr)
switch (type) {
case OBJ_BLOB:
- if (!dry_run && size > big_file_threshold) {
+ if (!dry_run &&
+ size > repo_settings_get_big_file_threshold(the_repository)) {
stream_blob(size, nr);
return;
}
@@ -668,6 +671,7 @@ int cmd_unpack_objects(int argc,
the_hash_algo->init_fn(&ctx);
unpack_all();
git_hash_update(&ctx, buffer, offset);
+ the_hash_algo->init_fn(&tmp_ctx);
git_hash_clone(&tmp_ctx, &ctx);
git_hash_final_oid(&oid, &tmp_ctx);
if (strict) {
diff --git a/builtin/update-index.c b/builtin/update-index.c
index b2f6b1a3fb..538b619ba4 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -304,7 +304,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
if (index_path(the_repository->index, &ce->oid, path, st,
- info_only ? 0 : HASH_WRITE_OBJECT)) {
+ info_only ? 0 : INDEX_WRITE_OBJECT)) {
discard_cache_entry(ce);
return -1;
}
@@ -964,29 +964,51 @@ int cmd_update_index(int argc,
N_("like --refresh, but ignore assume-unchanged setting"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
really_refresh_callback),
- {OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL,
- N_("<mode>,<object>,<path>"),
- N_("add the specified entry to the index"),
- PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
- PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
- NULL, 0,
- cacheinfo_callback},
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .long_name = "cacheinfo",
+ .argh = N_("<mode>,<object>,<path>"),
+ .help = N_("add the specified entry to the index"),
+ .flags = PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
+ PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+ .ll_callback = cacheinfo_callback,
+ },
OPT_CALLBACK_F(0, "chmod", &set_executable_bit, "(+|-)x",
N_("override the executable bit of the listed files"),
PARSE_OPT_NONEG,
chmod_callback),
- {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
- N_("mark files as \"not changing\""),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
- {OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
- N_("clear assumed-unchanged bit"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
- {OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL,
- N_("mark files as \"index-only\""),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
- {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
- N_("clear skip-worktree bit"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "assume-unchanged",
+ .value = &mark_valid_only,
+ .help = N_("mark files as \"not changing\""),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = MARK_FLAG,
+ },
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "no-assume-unchanged",
+ .value = &mark_valid_only,
+ .help = N_("clear assumed-unchanged bit"),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = UNMARK_FLAG,
+ },
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "skip-worktree",
+ .value = &mark_skip_worktree_only,
+ .help = N_("mark files as \"index-only\""),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = MARK_FLAG,
+ },
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "no-skip-worktree",
+ .value = &mark_skip_worktree_only,
+ .help = N_("clear skip-worktree bit"),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = UNMARK_FLAG,
+ },
OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries,
N_("do not touch index-only entries")),
OPT_SET_INT(0, "info-only", &info_only,
@@ -995,22 +1017,39 @@ int cmd_update_index(int argc,
N_("remove named paths even if present in worktree"), 1),
OPT_BOOL('z', NULL, &nul_term_line,
N_("with --stdin: input lines are terminated by null bytes")),
- {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
- N_("read list of paths to be updated from standard input"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG,
- NULL, 0, stdin_callback},
- {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
- N_("add entries from standard input to the index"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG,
- NULL, 0, stdin_cacheinfo_callback},
- {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
- N_("repopulate stages #2 and #3 for the listed paths"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG,
- NULL, 0, unresolve_callback},
- {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
- N_("only update entries that differ from HEAD"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG,
- NULL, 0, reupdate_callback},
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .long_name = "stdin",
+ .value = &read_from_stdin,
+ .help = N_("read list of paths to be updated from standard input"),
+ .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ .ll_callback = stdin_callback,
+ },
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .long_name = "index-info",
+ .value = &nul_term_line,
+ .help = N_("add entries from standard input to the index"),
+ .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ .ll_callback = stdin_cacheinfo_callback,
+ },
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .long_name = "unresolve",
+ .value = &has_errors,
+ .help = N_("repopulate stages #2 and #3 for the listed paths"),
+ .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ .ll_callback = unresolve_callback,
+ },
+ {
+ .type = OPTION_LOWLEVEL_CALLBACK,
+ .short_name = 'g',
+ .long_name = "again",
+ .value = &has_errors,
+ .help = N_("only update entries that differ from HEAD"),
+ .flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ .ll_callback = reupdate_callback,
+ },
OPT_BIT(0, "ignore-missing", &refresh_args.flags,
N_("ignore files missing from worktree"),
REFRESH_IGNORE_MISSING),
@@ -1036,12 +1075,22 @@ int cmd_update_index(int argc,
N_("write out the index even if is not flagged as changed"), 1),
OPT_BOOL(0, "fsmonitor", &fsmonitor,
N_("enable or disable file system monitor")),
- {OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only, NULL,
- N_("mark files as fsmonitor valid"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
- {OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only, NULL,
- N_("clear fsmonitor valid bit"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "fsmonitor-valid",
+ .value = &mark_fsmonitor_only,
+ .help = N_("mark files as fsmonitor valid"),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = MARK_FLAG,
+ },
+ {
+ .type = OPTION_SET_INT,
+ .long_name = "no-fsmonitor-valid",
+ .value = &mark_fsmonitor_only,
+ .help = N_("clear fsmonitor valid bit"),
+ .flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ .defval = UNMARK_FLAG,
+ },
OPT_END()
};
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 4d35bdc4b4..2b1e336ba1 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -5,6 +5,7 @@
#include "config.h"
#include "gettext.h"
#include "hash.h"
+#include "hex.h"
#include "refs.h"
#include "object-name.h"
#include "parse-options.h"
@@ -13,7 +14,7 @@
static const char * const git_update_ref_usage[] = {
N_("git update-ref [<options>] -d <refname> [<old-oid>]"),
N_("git update-ref [<options>] <refname> <new-oid> [<old-oid>]"),
- N_("git update-ref [<options>] --stdin [-z]"),
+ N_("git update-ref [<options>] --stdin [-z] [--batch-updates]"),
NULL
};
@@ -179,7 +180,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 +199,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 +302,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;
@@ -500,7 +504,7 @@ static void parse_cmd_symref_verify(struct ref_transaction *transaction,
*/
old_target = parse_next_refname(&next);
if (!old_target)
- oidcpy(&old_oid, null_oid());
+ oidcpy(&old_oid, null_oid(the_hash_algo));
if (*next != line_termination)
die("symref-verify %s: extra input: %s", refname, next);
@@ -562,6 +566,49 @@ static void parse_cmd_abort(struct ref_transaction *transaction,
report_ok("abort");
}
+static void print_rejected_refs(const char *refname,
+ const struct object_id *old_oid,
+ const struct object_id *new_oid,
+ const char *old_target,
+ const char *new_target,
+ enum ref_transaction_error err,
+ void *cb_data UNUSED)
+{
+ struct strbuf sb = STRBUF_INIT;
+ const char *reason = "";
+
+ switch (err) {
+ case REF_TRANSACTION_ERROR_NAME_CONFLICT:
+ reason = "refname conflict";
+ break;
+ case REF_TRANSACTION_ERROR_CREATE_EXISTS:
+ reason = "reference already exists";
+ break;
+ case REF_TRANSACTION_ERROR_NONEXISTENT_REF:
+ reason = "reference does not exist";
+ break;
+ case REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE:
+ reason = "incorrect old value provided";
+ break;
+ case REF_TRANSACTION_ERROR_INVALID_NEW_VALUE:
+ reason = "invalid new value provided";
+ break;
+ case REF_TRANSACTION_ERROR_EXPECTED_SYMREF:
+ reason = "expected symref but found regular ref";
+ break;
+ default:
+ reason = "unkown failure";
+ }
+
+ strbuf_addf(&sb, "rejected %s %s %s %s\n", refname,
+ new_oid ? oid_to_hex(new_oid) : new_target,
+ old_oid ? oid_to_hex(old_oid) : old_target,
+ reason);
+
+ fwrite(sb.buf, sb.len, 1, stdout);
+ strbuf_release(&sb);
+}
+
static void parse_cmd_commit(struct ref_transaction *transaction,
const char *next, const char *end UNUSED)
{
@@ -570,6 +617,10 @@ static void parse_cmd_commit(struct ref_transaction *transaction,
die("commit: extra input: %s", next);
if (ref_transaction_commit(transaction, &error))
die("commit: %s", error.buf);
+
+ ref_transaction_for_each_rejected_update(transaction,
+ print_rejected_refs, NULL);
+
report_ok("commit");
ref_transaction_free(transaction);
}
@@ -606,7 +657,7 @@ static const struct parse_cmd {
{ "commit", parse_cmd_commit, 0, UPDATE_REFS_CLOSED },
};
-static void update_refs_stdin(void)
+static void update_refs_stdin(unsigned int flags)
{
struct strbuf input = STRBUF_INIT, err = STRBUF_INIT;
enum update_refs_state state = UPDATE_REFS_OPEN;
@@ -614,7 +665,7 @@ static void update_refs_stdin(void)
int i, j;
transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
- 0, &err);
+ flags, &err);
if (!transaction)
die("%s", err.buf);
@@ -682,7 +733,7 @@ static void update_refs_stdin(void)
*/
state = cmd->state;
transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
- 0, &err);
+ flags, &err);
if (!transaction)
die("%s", err.buf);
@@ -698,6 +749,8 @@ static void update_refs_stdin(void)
/* Commit by default if no transaction was requested. */
if (ref_transaction_commit(transaction, &err))
die("%s", err.buf);
+ ref_transaction_for_each_rejected_update(transaction,
+ print_rejected_refs, NULL);
ref_transaction_free(transaction);
break;
case UPDATE_REFS_STARTED:
@@ -724,6 +777,8 @@ int cmd_update_ref(int argc,
struct object_id oid, oldoid;
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
int create_reflog = 0;
+ unsigned int flags = 0;
+
struct option options[] = {
OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
@@ -732,6 +787,8 @@ int cmd_update_ref(int argc,
OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")),
OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")),
OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create a reflog")),
+ OPT_BIT('0', "batch-updates", &flags, N_("batch reference updates"),
+ REF_TRANSACTION_ALLOW_FAILURE),
OPT_END(),
};
@@ -753,8 +810,10 @@ int cmd_update_ref(int argc,
usage_with_options(git_update_ref_usage, options);
if (end_null)
line_termination = '\0';
- update_refs_stdin();
+ update_refs_stdin(flags);
return 0;
+ } else if (flags & REF_TRANSACTION_ALLOW_FAILURE) {
+ die("--batch-updates can only be used with --stdin");
}
if (end_null)
@@ -772,7 +831,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 +843,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 d7467290a8..ba702d30ef 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -20,8 +20,8 @@ int cmd_update_server_info(int argc,
OPT_END()
};
- if (repo)
- repo_config(repo, git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
+
argc = parse_options(argc, argv, prefix, options,
update_server_info_usage, 0);
if (argc > 0)
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index 779b7988ca..5f749a30da 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -5,7 +5,6 @@
*
* Based on git-verify-tag
*/
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -33,15 +32,15 @@ static int run_gpg_verify(struct commit *commit, unsigned flags)
return ret;
}
-static int verify_commit(const char *name, unsigned flags)
+static int verify_commit(struct repository *repo, const char *name, unsigned flags)
{
struct object_id oid;
struct object *obj;
- if (repo_get_oid(the_repository, name, &oid))
+ if (repo_get_oid(repo, name, &oid))
return error("commit '%s' not found.", name);
- obj = parse_object(the_repository, &oid);
+ obj = parse_object(repo, &oid);
if (!obj)
return error("%s: unable to read file.", name);
if (obj->type != OBJ_COMMIT)
@@ -54,7 +53,7 @@ static int verify_commit(const char *name, unsigned flags)
int cmd_verify_commit(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int i = 1, verbose = 0, had_error = 0;
unsigned flags = 0;
@@ -64,7 +63,7 @@ int cmd_verify_commit(int argc,
OPT_END()
};
- git_config(git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
argc = parse_options(argc, argv, prefix, verify_commit_options,
verify_commit_usage, PARSE_OPT_KEEP_ARGV0);
@@ -78,7 +77,7 @@ int cmd_verify_commit(int argc,
* was received in the process of writing the gpg input: */
signal(SIGPIPE, SIG_IGN);
while (i < argc)
- if (verify_commit(argv[i++], flags))
+ if (verify_commit(repo, argv[i++], flags))
had_error = 1;
return had_error;
}
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index f6b97048a5..ed1c40338f 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -5,7 +5,6 @@
*
* Based on git-verify-tag.sh
*/
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -23,7 +22,7 @@ static const char * const verify_tag_usage[] = {
int cmd_verify_tag(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int i = 1, verbose = 0, had_error = 0;
unsigned flags = 0;
@@ -35,7 +34,7 @@ int cmd_verify_tag(int argc,
OPT_END()
};
- git_config(git_default_config, NULL);
+ repo_config(repo, git_default_config, NULL);
argc = parse_options(argc, argv, prefix, verify_tag_options,
verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
@@ -56,7 +55,7 @@ int cmd_verify_tag(int argc,
struct object_id oid;
const char *name = argv[i++];
- if (repo_get_oid(the_repository, name, &oid)) {
+ if (repo_get_oid(repo, name, &oid)) {
had_error = !!error("tag '%s' not found.", name);
continue;
}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 48448a8355..2dceeeed8b 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -348,7 +348,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)
char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir);
if (file_exists(from_file)) {
- if (safe_create_leading_directories(to_file) ||
+ if (safe_create_leading_directories(the_repository, to_file) ||
copy_file(to_file, from_file, 0666))
error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"),
from_file, to_file);
@@ -367,7 +367,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
struct config_set cs = { { 0 } };
int bare;
- if (safe_create_leading_directories(to_file) ||
+ if (safe_create_leading_directories(the_repository, to_file) ||
copy_file(to_file, from_file, 0666)) {
error(_("failed to copy worktree config from '%s' to '%s'"),
from_file, to_file);
@@ -466,7 +466,7 @@ static int add_worktree(const char *path, const char *refname,
name = sb_name.buf;
repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name);
len = sb_repo.len;
- if (safe_create_leading_directories_const(sb_repo.buf))
+ if (safe_create_leading_directories_const(the_repository, sb_repo.buf))
die_errno(_("could not create leading directories of '%s'"),
sb_repo.buf);
@@ -498,7 +498,7 @@ static int add_worktree(const char *path, const char *refname,
write_file(sb.buf, _("initializing"));
strbuf_addf(&sb_git, "%s/.git", path);
- if (safe_create_leading_directories_const(sb_git.buf))
+ if (safe_create_leading_directories_const(the_repository, sb_git.buf))
die_errno(_("could not create leading directories of '%s'"),
sb_git.buf);
junk_work_tree = xstrdup(path);
@@ -578,7 +578,7 @@ done:
strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL);
strvec_pushl(&opt.args,
- oid_to_hex(null_oid()),
+ oid_to_hex(null_oid(the_hash_algo)),
oid_to_hex(&commit->object.oid),
"1",
NULL);
@@ -621,7 +621,7 @@ static void print_preparing_worktree_line(int detach,
else {
struct commit *commit = lookup_commit_reference_by_name(branch);
if (!commit)
- BUG(_("unreachable: invalid reference: %s"), branch);
+ BUG("unreachable: invalid reference: %s", branch);
fprintf_ln(stderr, _("Preparing worktree (detached HEAD %s)"),
repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV));
}
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 43f233e69b..5a8dc377ec 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -31,10 +31,14 @@ int cmd_write_tree(int argc,
WRITE_TREE_MISSING_OK),
OPT_STRING(0, "prefix", &tree_prefix, N_("<prefix>/"),
N_("write tree object for a subdirectory <prefix>")),
- { OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
- N_("only useful for debugging"),
- PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
- WRITE_TREE_IGNORE_CACHE_TREE },
+ {
+ .type = OPTION_BIT,
+ .long_name = "ignore-cache-tree",
+ .value = &flags,
+ .help = N_("only useful for debugging"),
+ .flags = PARSE_OPT_HIDDEN | PARSE_OPT_NOARG,
+ .defval = WRITE_TREE_IGNORE_CACHE_TREE,
+ },
OPT_END()
};