aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c2
-rw-r--r--builtin/backfill.c147
-rw-r--r--builtin/bugreport.c13
-rw-r--r--builtin/check-mailmap.c2
-rw-r--r--builtin/clone.c354
-rw-r--r--builtin/commit.c8
-rw-r--r--builtin/config.c8
-rw-r--r--builtin/difftool.c95
-rw-r--r--builtin/fast-import.c4
-rw-r--r--builtin/fetch.c25
-rw-r--r--builtin/fsck.c10
-rw-r--r--builtin/gc.c25
-rw-r--r--builtin/init-db.c8
-rw-r--r--builtin/log.c6
-rw-r--r--builtin/merge-tree.c11
-rw-r--r--builtin/notes.c9
-rw-r--r--builtin/rebase.c2
-rw-r--r--builtin/receive-pack.c4
-rw-r--r--builtin/remote.c6
-rw-r--r--builtin/replace.c2
-rw-r--r--builtin/replay.c7
-rw-r--r--builtin/rerere.c11
-rw-r--r--builtin/rev-list.c106
-rw-r--r--builtin/rev-parse.c6
-rw-r--r--builtin/submodule--helper.c4
-rw-r--r--builtin/tag.c2
-rw-r--r--builtin/update-server-info.c8
-rw-r--r--builtin/worktree.c43
28 files changed, 622 insertions, 306 deletions
diff --git a/builtin/am.c b/builtin/am.c
index 390b463144..2921bb89ef 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -158,7 +158,7 @@ static void am_state_init(struct am_state *state)
memset(state, 0, sizeof(*state));
- state->dir = git_pathdup("rebase-apply");
+ state->dir = repo_git_path(the_repository, "rebase-apply");
state->prec = 4;
diff --git a/builtin/backfill.c b/builtin/backfill.c
new file mode 100644
index 0000000000..33e1ea2f84
--- /dev/null
+++ b/builtin/backfill.c
@@ -0,0 +1,147 @@
+/* We need this macro to access core_apply_sparse_checkout */
+#define USE_THE_REPOSITORY_VARIABLE
+
+#include "builtin.h"
+#include "git-compat-util.h"
+#include "config.h"
+#include "parse-options.h"
+#include "repository.h"
+#include "commit.h"
+#include "dir.h"
+#include "environment.h"
+#include "hex.h"
+#include "tree.h"
+#include "tree-walk.h"
+#include "object.h"
+#include "object-store-ll.h"
+#include "oid-array.h"
+#include "oidset.h"
+#include "promisor-remote.h"
+#include "strmap.h"
+#include "string-list.h"
+#include "revision.h"
+#include "trace2.h"
+#include "progress.h"
+#include "packfile.h"
+#include "path-walk.h"
+
+static const char * const builtin_backfill_usage[] = {
+ N_("git backfill [--min-batch-size=<n>] [--[no-]sparse]"),
+ NULL
+};
+
+struct backfill_context {
+ struct repository *repo;
+ struct oid_array current_batch;
+ size_t min_batch_size;
+ int sparse;
+};
+
+static void backfill_context_clear(struct backfill_context *ctx)
+{
+ oid_array_clear(&ctx->current_batch);
+}
+
+static void download_batch(struct backfill_context *ctx)
+{
+ promisor_remote_get_direct(ctx->repo,
+ ctx->current_batch.oid,
+ ctx->current_batch.nr);
+ oid_array_clear(&ctx->current_batch);
+
+ /*
+ * We likely have a new packfile. Add it to the packed list to
+ * avoid possible duplicate downloads of the same objects.
+ */
+ reprepare_packed_git(ctx->repo);
+}
+
+static int fill_missing_blobs(const char *path UNUSED,
+ struct oid_array *list,
+ enum object_type type,
+ void *data)
+{
+ struct backfill_context *ctx = data;
+
+ if (type != OBJ_BLOB)
+ return 0;
+
+ for (size_t i = 0; i < list->nr; i++) {
+ if (!has_object(ctx->repo, &list->oid[i],
+ OBJECT_INFO_FOR_PREFETCH))
+ oid_array_append(&ctx->current_batch, &list->oid[i]);
+ }
+
+ if (ctx->current_batch.nr >= ctx->min_batch_size)
+ download_batch(ctx);
+
+ return 0;
+}
+
+static int do_backfill(struct backfill_context *ctx)
+{
+ struct rev_info revs;
+ struct path_walk_info info = PATH_WALK_INFO_INIT;
+ int ret;
+
+ if (ctx->sparse) {
+ CALLOC_ARRAY(info.pl, 1);
+ if (get_sparse_checkout_patterns(info.pl)) {
+ path_walk_info_clear(&info);
+ return error(_("problem loading sparse-checkout"));
+ }
+ }
+
+ repo_init_revisions(ctx->repo, &revs, "");
+ handle_revision_arg("HEAD", &revs, 0, 0);
+
+ info.blobs = 1;
+ info.tags = info.commits = info.trees = 0;
+
+ info.revs = &revs;
+ info.path_fn = fill_missing_blobs;
+ info.path_fn_data = ctx;
+
+ ret = walk_objects_by_path(&info);
+
+ /* Download the objects that did not fill a batch. */
+ if (!ret)
+ download_batch(ctx);
+
+ path_walk_info_clear(&info);
+ release_revisions(&revs);
+ return ret;
+}
+
+int cmd_backfill(int argc, const char **argv, const char *prefix, struct repository *repo)
+{
+ int result;
+ struct backfill_context ctx = {
+ .repo = repo,
+ .current_batch = OID_ARRAY_INIT,
+ .min_batch_size = 50000,
+ .sparse = 0,
+ };
+ struct option options[] = {
+ OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size,
+ N_("Minimum number of objects to request at a time")),
+ OPT_BOOL(0, "sparse", &ctx.sparse,
+ N_("Restrict the missing objects to the current sparse-checkout")),
+ OPT_END(),
+ };
+
+ show_usage_with_options_if_asked(argc, argv,
+ builtin_backfill_usage, options);
+
+ argc = parse_options(argc, argv, prefix, options, builtin_backfill_usage,
+ 0);
+
+ repo_config(repo, git_default_config, NULL);
+
+ if (ctx.sparse < 0)
+ ctx.sparse = core_apply_sparse_checkout;
+
+ result = do_backfill(&ctx);
+ backfill_context_clear(&ctx);
+ return result;
+}
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 0ac59cc8dc..66d64bfd5a 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -12,10 +12,10 @@
#include "diagnose.h"
#include "object-file.h"
#include "setup.h"
+#include "version.h"
static void get_system_info(struct strbuf *sys_info)
{
- struct utsname uname_info;
char *shell = NULL;
/* get git version from native cmd */
@@ -24,16 +24,7 @@ static void get_system_info(struct strbuf *sys_info)
/* system call for other version info */
strbuf_addstr(sys_info, "uname: ");
- if (uname(&uname_info))
- strbuf_addf(sys_info, _("uname() failed with error '%s' (%d)\n"),
- strerror(errno),
- errno);
- else
- strbuf_addf(sys_info, "%s %s %s %s\n",
- uname_info.sysname,
- uname_info.release,
- uname_info.version,
- uname_info.machine);
+ get_uname_info(sys_info, 1);
strbuf_addstr(sys_info, _("compiler info: "));
get_compiler_info(sys_info);
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
index df00b5ee13..be2cebe121 100644
--- a/builtin/check-mailmap.c
+++ b/builtin/check-mailmap.c
@@ -35,7 +35,7 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
mail = ident.mail_begin;
maillen = ident.mail_end - ident.mail_begin;
} else {
- name = NULL;
+ name = "";
namelen = 0;
mail = contact;
maillen = strlen(contact);
diff --git a/builtin/clone.c b/builtin/clone.c
index fd001d800c..f14229abf4 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -56,42 +56,30 @@
* - dropping use-separate-remote and no-separate-remote compatibility
*
*/
-static const char * const builtin_clone_usage[] = {
- N_("git clone [<options>] [--] <repo> [<dir>]"),
- NULL
+
+struct clone_opts {
+ int wants_head;
+ int detach;
};
+#define CLONE_OPTS_INIT { \
+ .wants_head = 1 /* default enabled */ \
+}
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
static int option_local = -1, option_no_hardlinks, option_shared;
-static int option_no_tags;
+static int option_tags = 1; /* default enabled */
static int option_shallow_submodules;
-static int option_reject_shallow = -1; /* unspecified */
static int config_reject_shallow = -1; /* unspecified */
-static int deepen;
-static char *option_template, *option_depth, *option_since;
-static char *option_origin = NULL;
static char *remote_name = NULL;
static char *option_branch = NULL;
-static struct string_list option_not = STRING_LIST_INIT_NODUP;
-static const char *real_git_dir;
-static const char *ref_format;
-static const char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
-static int option_progress = -1;
-static int option_sparse_checkout;
-static enum transport_family family;
-static struct string_list option_config = STRING_LIST_INIT_NODUP;
static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
-static int option_dissociate;
static int max_jobs = -1;
static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
-static int option_filter_submodules = -1; /* unspecified */
static int config_filter_submodules = -1; /* unspecified */
-static struct string_list server_options = STRING_LIST_INIT_NODUP;
static int option_remote_submodules;
-static const char *bundle_uri;
static int recurse_submodules_cb(const struct option *opt,
const char *arg, int unset)
@@ -107,78 +95,6 @@ static int recurse_submodules_cb(const struct option *opt,
return 0;
}
-static struct option builtin_clone_options[] = {
- OPT__VERBOSITY(&option_verbosity),
- OPT_BOOL(0, "progress", &option_progress,
- N_("force progress reporting")),
- OPT_BOOL(0, "reject-shallow", &option_reject_shallow,
- N_("don't clone shallow repository")),
- OPT_BOOL('n', "no-checkout", &option_no_checkout,
- N_("don't create a checkout")),
- OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
- OPT_HIDDEN_BOOL(0, "naked", &option_bare,
- N_("create a bare repository")),
- OPT_BOOL(0, "mirror", &option_mirror,
- N_("create a mirror repository (implies --bare)")),
- OPT_BOOL('l', "local", &option_local,
- N_("to clone from a local repository")),
- OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
- N_("don't use local hardlinks, always copy")),
- OPT_BOOL('s', "shared", &option_shared,
- N_("setup as shared repository")),
- { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
- N_("pathspec"), N_("initialize submodules in the clone"),
- PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
- OPT_ALIAS(0, "recursive", "recurse-submodules"),
- OPT_INTEGER('j', "jobs", &max_jobs,
- N_("number of submodules cloned in parallel")),
- OPT_STRING(0, "template", &option_template, N_("template-directory"),
- N_("directory from which templates will be used")),
- OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
- N_("reference repository")),
- OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
- N_("repo"), N_("reference repository")),
- OPT_BOOL(0, "dissociate", &option_dissociate,
- N_("use --reference only while cloning")),
- OPT_STRING('o', "origin", &option_origin, N_("name"),
- N_("use <name> instead of 'origin' to track upstream")),
- OPT_STRING('b', "branch", &option_branch, N_("branch"),
- N_("checkout <branch> instead of the remote's HEAD")),
- OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
- N_("path to git-upload-pack on the remote")),
- OPT_STRING(0, "depth", &option_depth, N_("depth"),
- N_("create a shallow clone of that depth")),
- OPT_STRING(0, "shallow-since", &option_since, N_("time"),
- N_("create a shallow clone since a specific time")),
- OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"),
- N_("deepen history of shallow clone, excluding ref")),
- OPT_BOOL(0, "single-branch", &option_single_branch,
- N_("clone only one branch, HEAD or --branch")),
- OPT_BOOL(0, "no-tags", &option_no_tags,
- N_("don't clone any tags, and make later fetches not to follow them")),
- OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
- N_("any cloned submodules will be shallow")),
- OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
- N_("separate git dir from working tree")),
- OPT_STRING(0, "ref-format", &ref_format, N_("format"),
- N_("specify the reference format to use")),
- OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
- N_("set config inside the new repository")),
- OPT_STRING_LIST(0, "server-option", &server_options,
- N_("server-specific"), N_("option to transmit")),
- OPT_IPVERSION(&family),
- OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
- OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules,
- N_("apply partial clone filters to submodules")),
- OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
- N_("any cloned submodules will use their remote-tracking branch")),
- OPT_BOOL(0, "sparse", &option_sparse_checkout,
- N_("initialize sparse-checkout file to include only files at root")),
- OPT_STRING(0, "bundle-uri", &bundle_uri,
- N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")),
- OPT_END()
-};
-
static const char *get_repo_path_1(struct strbuf *path, int *is_bundle)
{
static const char *suffix[] = { "/.git", "", ".git/.git", ".git" };
@@ -521,51 +437,31 @@ static struct ref *find_remote_branch(const struct ref *refs, const char *branch
return ref;
}
-static struct ref *wanted_peer_refs(const struct ref *refs,
- struct refspec *refspec)
+static struct ref *wanted_peer_refs(struct clone_opts *opts,
+ const struct ref *refs,
+ struct refspec *refspec)
{
- struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
- struct ref *local_refs = head;
- struct ref **tail = head ? &head->next : &local_refs;
- struct refspec_item tag_refspec;
-
- refspec_item_init(&tag_refspec, TAG_REFSPEC, 0);
-
- if (option_single_branch) {
- struct ref *remote_head = NULL;
-
- if (!option_branch)
- remote_head = guess_remote_head(head, refs, 0);
- else {
- free_one_ref(head);
- local_refs = head = NULL;
- tail = &local_refs;
- remote_head = copy_ref(find_remote_branch(refs, option_branch));
- }
-
- if (!remote_head && option_branch)
- warning(_("Could not find remote branch %s to clone."),
- option_branch);
- else {
- int i;
- for (i = 0; i < refspec->nr; i++)
- get_fetch_map(remote_head, &refspec->items[i],
- &tail, 0);
-
- /* if --branch=tag, pull the requested tag explicitly */
- get_fetch_map(remote_head, &tag_refspec, &tail, 0);
- }
- free_refs(remote_head);
- } else {
- int i;
- for (i = 0; i < refspec->nr; i++)
- get_fetch_map(refs, &refspec->items[i], &tail, 0);
+ struct ref *local_refs = NULL;
+ struct ref **tail = &local_refs;
+ struct ref *to_free = NULL;
+
+ if (opts->wants_head) {
+ struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
+ if (head)
+ tail_link_ref(head, &tail);
+ if (option_single_branch)
+ refs = to_free = guess_remote_head(head, refs, 0);
+ } else if (option_single_branch) {
+ local_refs = NULL;
+ tail = &local_refs;
+ refs = to_free = copy_ref(find_remote_branch(refs, option_branch));
}
- if (!option_mirror && !option_single_branch && !option_no_tags)
- get_fetch_map(refs, &tag_refspec, &tail, 0);
+ for (size_t i = 0; i < refspec->nr; i++)
+ get_fetch_map(refs, &refspec->items[i], &tail, 0);
+
+ free_one_ref(to_free);
- refspec_item_clear(&tag_refspec);
return local_refs;
}
@@ -654,7 +550,7 @@ static void update_remote_refs(const struct ref *refs,
if (refs) {
write_remote_refs(mapped_refs);
- if (option_single_branch && !option_no_tags)
+ if (option_single_branch && option_tags)
write_followtags(refs, msg);
}
@@ -670,11 +566,11 @@ static void update_remote_refs(const struct ref *refs,
}
}
-static void update_head(const struct ref *our, const struct ref *remote,
+static void update_head(struct clone_opts *opts, const struct ref *our, const struct ref *remote,
const char *unborn, const char *msg)
{
const char *head;
- if (our && skip_prefix(our->name, "refs/heads/", &head)) {
+ if (our && !opts->detach && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0)
die(_("unable to update HEAD"));
@@ -685,8 +581,9 @@ static void update_head(const struct ref *our, const struct ref *remote,
install_branch_config(0, head, remote_name, our->name);
}
} else if (our) {
- struct commit *c = lookup_commit_reference(the_repository,
- &our->old_oid);
+ struct commit *c = lookup_commit_or_die(&our->old_oid,
+ our->name);
+
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
refs_update_ref(get_main_ref_store(the_repository), msg,
"HEAD", &c->object.oid, NULL, REF_NO_DEREF,
@@ -938,7 +835,7 @@ static void write_refspec_config(const char *src_ref_prefix,
static void dissociate_from_references(void)
{
- char *alternates = git_pathdup("objects/info/alternates");
+ char *alternates = repo_git_path(the_repository, "objects/info/alternates");
if (!access(alternates, F_OK)) {
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -989,10 +886,108 @@ int cmd_clone(int argc,
int hash_algo;
enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
const int do_not_override_repo_unix_permissions = -1;
+ int option_reject_shallow = -1; /* unspecified */
+ int deepen = 0;
+ char *option_template = NULL, *option_depth = NULL, *option_since = NULL;
+ char *option_origin = NULL;
+ struct string_list option_not = STRING_LIST_INIT_NODUP;
+ const char *real_git_dir = NULL;
+ const char *ref_format = NULL;
+ const char *option_upload_pack = "git-upload-pack";
+ int option_progress = -1;
+ int option_sparse_checkout = 0;
+ enum transport_family family = TRANSPORT_FAMILY_ALL;
+ struct string_list option_config = STRING_LIST_INIT_DUP;
+ int option_dissociate = 0;
+ int option_filter_submodules = -1; /* unspecified */
+ struct string_list server_options = STRING_LIST_INIT_NODUP;
+ const char *bundle_uri = NULL;
+ char *option_rev = NULL;
+
+ struct clone_opts opts = CLONE_OPTS_INIT;
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
+ struct option builtin_clone_options[] = {
+ OPT__VERBOSITY(&option_verbosity),
+ OPT_BOOL(0, "progress", &option_progress,
+ N_("force progress reporting")),
+ OPT_BOOL(0, "reject-shallow", &option_reject_shallow,
+ N_("don't clone shallow repository")),
+ OPT_BOOL('n', "no-checkout", &option_no_checkout,
+ N_("don't create a checkout")),
+ OPT_BOOL(0, "bare", &option_bare, N_("create a bare repository")),
+ OPT_HIDDEN_BOOL(0, "naked", &option_bare,
+ N_("create a bare repository")),
+ OPT_BOOL(0, "mirror", &option_mirror,
+ N_("create a mirror repository (implies --bare)")),
+ OPT_BOOL('l', "local", &option_local,
+ N_("to clone from a local repository")),
+ OPT_BOOL(0, "no-hardlinks", &option_no_hardlinks,
+ N_("don't use local hardlinks, always copy")),
+ OPT_BOOL('s', "shared", &option_shared,
+ N_("setup as shared repository")),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
+ N_("pathspec"), N_("initialize submodules in the clone"),
+ PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
+ OPT_ALIAS(0, "recursive", "recurse-submodules"),
+ OPT_INTEGER('j', "jobs", &max_jobs,
+ N_("number of submodules cloned in parallel")),
+ OPT_STRING(0, "template", &option_template, N_("template-directory"),
+ N_("directory from which templates will be used")),
+ OPT_STRING_LIST(0, "reference", &option_required_reference, N_("repo"),
+ N_("reference repository")),
+ OPT_STRING_LIST(0, "reference-if-able", &option_optional_reference,
+ N_("repo"), N_("reference repository")),
+ OPT_BOOL(0, "dissociate", &option_dissociate,
+ N_("use --reference only while cloning")),
+ OPT_STRING('o', "origin", &option_origin, N_("name"),
+ N_("use <name> instead of 'origin' to track upstream")),
+ OPT_STRING('b', "branch", &option_branch, N_("branch"),
+ N_("checkout <branch> instead of the remote's HEAD")),
+ OPT_STRING(0, "revision", &option_rev, N_("rev"),
+ N_("clone single revision <rev> and check out")),
+ OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
+ N_("path to git-upload-pack on the remote")),
+ OPT_STRING(0, "depth", &option_depth, N_("depth"),
+ N_("create a shallow clone of that depth")),
+ OPT_STRING(0, "shallow-since", &option_since, N_("time"),
+ N_("create a shallow clone since a specific time")),
+ OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"),
+ N_("deepen history of shallow clone, excluding ref")),
+ OPT_BOOL(0, "single-branch", &option_single_branch,
+ N_("clone only one branch, HEAD or --branch")),
+ OPT_BOOL(0, "tags", &option_tags,
+ N_("clone tags, and make later fetches not to follow them")),
+ OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
+ N_("any cloned submodules will be shallow")),
+ OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+ N_("separate git dir from working tree")),
+ OPT_STRING(0, "ref-format", &ref_format, N_("format"),
+ N_("specify the reference format to use")),
+ OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
+ N_("set config inside the new repository")),
+ OPT_STRING_LIST(0, "server-option", &server_options,
+ N_("server-specific"), N_("option to transmit")),
+ OPT_IPVERSION(&family),
+ OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
+ OPT_BOOL(0, "also-filter-submodules", &option_filter_submodules,
+ N_("apply partial clone filters to submodules")),
+ OPT_BOOL(0, "remote-submodules", &option_remote_submodules,
+ N_("any cloned submodules will use their remote-tracking branch")),
+ OPT_BOOL(0, "sparse", &option_sparse_checkout,
+ N_("initialize sparse-checkout file to include only files at root")),
+ OPT_STRING(0, "bundle-uri", &bundle_uri,
+ N_("uri"), N_("a URI for downloading bundles before fetching from origin remote")),
+ OPT_END()
+ };
+
+ const char * const builtin_clone_usage[] = {
+ N_("git clone [<options>] [--] <repo> [<dir>]"),
+ NULL
+ };
+
packet_trace_identity("clone");
git_config(git_clone_config, NULL);
@@ -1019,8 +1014,10 @@ int cmd_clone(int argc,
die(_("unknown ref storage format '%s'"), ref_format);
}
- if (option_mirror)
+ if (option_mirror) {
option_bare = 1;
+ option_tags = 0;
+ }
if (option_bare) {
if (real_git_dir)
@@ -1138,8 +1135,8 @@ int cmd_clone(int argc,
for_each_string_list_item(item, &option_recurse_submodules) {
strbuf_addf(&sb, "submodule.active=%s",
item->string);
- string_list_append(&option_config,
- strbuf_detach(&sb, NULL));
+ string_list_append(&option_config, sb.buf);
+ strbuf_reset(&sb);
}
if (!git_config_get_bool("submodule.stickyRecursiveClone", &val) &&
@@ -1161,6 +1158,8 @@ int cmd_clone(int argc,
string_list_append(&option_config,
"submodule.alternateErrorStrategy=info");
}
+
+ strbuf_release(&sb);
}
/*
@@ -1220,7 +1219,7 @@ int cmd_clone(int argc,
strbuf_reset(&buf);
strbuf_addf(&buf, "%s/refs", git_dir);
- safe_create_dir(buf.buf, 1);
+ safe_create_dir(the_repository, buf.buf, 1);
/*
* additional config can be injected with -c, make sure it's included
@@ -1285,7 +1284,7 @@ int cmd_clone(int argc,
strbuf_addstr(&branch_top, src_ref_prefix);
git_config_set("core.bare", "true");
- } else {
+ } else if (!option_rev) {
strbuf_addf(&branch_top, "refs/remotes/%s/", remote_name);
}
@@ -1293,7 +1292,7 @@ int cmd_clone(int argc,
git_config_set(key.buf, repo);
strbuf_reset(&key);
- if (option_no_tags) {
+ if (!option_tags) {
strbuf_addf(&key, "remote.%s.tagOpt", remote_name);
git_config_set(key.buf, "--no-tags");
strbuf_reset(&key);
@@ -1304,8 +1303,9 @@ int cmd_clone(int argc,
remote = remote_get_early(remote_name);
- refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
- branch_top.buf);
+ if (!option_rev)
+ refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
+ branch_top.buf);
path = get_repo_path(remote->url.v[0], &is_bundle);
is_local = option_local != 0 && path && !is_bundle;
@@ -1348,6 +1348,11 @@ int cmd_clone(int argc,
transport_set_option(transport, TRANS_OPT_KEEP, "yes");
+ die_for_incompatible_opt2(!!option_rev, "--revision",
+ !!option_branch, "--branch");
+ die_for_incompatible_opt2(!!option_rev, "--revision",
+ option_mirror, "--mirror");
+
if (reject_shallow)
transport_set_option(transport, TRANS_OPT_REJECT_SHALLOW, "1");
if (option_depth)
@@ -1359,9 +1364,13 @@ int cmd_clone(int argc,
if (option_not.nr)
transport_set_option(transport, TRANS_OPT_DEEPEN_NOT,
(const char *)&option_not);
- if (option_single_branch)
+ if (option_single_branch) {
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
+ if (option_branch)
+ opts.wants_head = 0;
+ }
+
if (option_upload_pack)
transport_set_option(transport, TRANS_OPT_UPLOADPACK,
option_upload_pack);
@@ -1380,15 +1389,38 @@ int cmd_clone(int argc,
if (transport->smart_options && !deepen && !filter_options.choice)
transport->smart_options->check_self_contained_and_connected = 1;
- strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
+ if (option_rev) {
+ option_tags = 0;
+ option_single_branch = 0;
+ opts.wants_head = 0;
+ opts.detach = 1;
+
+ refspec_append(&remote->fetch, option_rev);
+ }
+
+ if (option_tags || option_branch)
+ /*
+ * Add tags refspec when user asked for tags (implicitly) or
+ * specified --branch, whose argument might be a tag.
+ */
+ refspec_append(&remote->fetch, TAG_REFSPEC);
+
refspec_ref_prefixes(&remote->fetch,
&transport_ls_refs_options.ref_prefixes);
if (option_branch)
expand_ref_prefix(&transport_ls_refs_options.ref_prefixes,
option_branch);
- if (!option_no_tags)
- strvec_push(&transport_ls_refs_options.ref_prefixes,
- "refs/tags/");
+
+ /*
+ * As part of transport_get_remote_refs() the server tells us the hash
+ * algorithm, which we require to initialize the repo. But calling that
+ * function without any ref prefix, will cause the server to announce
+ * all known refs. If the argument passed to --revision was a hex oid,
+ * ref_prefixes will be empty so we fall back to asking about HEAD to
+ * reduce traffic from the server.
+ */
+ if (opts.wants_head || transport_ls_refs_options.ref_prefixes.nr == 0)
+ strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
refs = transport_get_remote_refs(transport, &transport_ls_refs_options);
@@ -1465,7 +1497,7 @@ int cmd_clone(int argc,
}
if (refs)
- mapped_refs = wanted_peer_refs(refs, &remote->fetch);
+ mapped_refs = wanted_peer_refs(&opts, refs, &remote->fetch);
if (mapped_refs) {
/*
@@ -1498,6 +1530,11 @@ int cmd_clone(int argc,
if (!our_head_points_at)
die(_("Remote branch %s not found in upstream %s"),
option_branch, remote_name);
+ } else if (option_rev) {
+ our_head_points_at = mapped_refs;
+ if (!our_head_points_at)
+ die(_("Remote revision %s not found in upstream %s"),
+ option_rev, remote_name);
} else if (remote_head_points_at) {
our_head_points_at = remote_head_points_at;
} else if (remote_head) {
@@ -1536,8 +1573,9 @@ int cmd_clone(int argc,
free(to_free);
}
- write_refspec_config(src_ref_prefix, our_head_points_at,
- remote_head_points_at, &branch_top);
+ if (!option_rev)
+ write_refspec_config(src_ref_prefix, our_head_points_at,
+ remote_head_points_at, &branch_top);
if (filter_options.choice)
partial_clone_register(remote_name, &filter_options);
@@ -1553,7 +1591,7 @@ int cmd_clone(int argc,
branch_top.buf, reflog_msg.buf, transport,
!is_local);
- update_head(our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
+ update_head(&opts, our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
/*
* We want to show progress for recursive submodule clones iff
@@ -1578,6 +1616,10 @@ int cmd_clone(int argc,
err = checkout(submodule_progress, filter_submodules,
ref_storage_format);
+ string_list_clear(&option_not, 0);
+ string_list_clear(&option_config, 0);
+ string_list_clear(&server_options, 0);
+
free(remote_name);
strbuf_release(&reflog_msg);
strbuf_release(&branch_top);
diff --git a/builtin/commit.c b/builtin/commit.c
index 9fb405dd4a..2f45968222 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
struct pathspec pathspec;
int refresh_flags = REFRESH_QUIET;
const char *ret;
+ char *path = NULL;
if (is_status)
refresh_flags |= REFRESH_UNMERGED;
@@ -524,9 +525,9 @@ static const char *prepare_index(const char **argv, const char *prefix,
if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to write new index file"));
- hold_lock_file_for_update(&false_lock,
- git_path("next-index-%"PRIuMAX,
- (uintmax_t) getpid()),
+ path = repo_git_path(the_repository, "next-index-%"PRIuMAX,
+ (uintmax_t) getpid());
+ hold_lock_file_for_update(&false_lock, path,
LOCK_DIE_ON_ERROR);
create_base_index(current_head);
@@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
out:
string_list_clear(&partial, 0);
clear_pathspec(&pathspec);
+ free(path);
return ret;
}
diff --git a/builtin/config.c b/builtin/config.c
index 16e6e30555..53a90094e3 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -775,13 +775,13 @@ static void location_options_init(struct config_location_options *opts,
opts->source.file = opts->file_to_free = git_system_config();
opts->source.scope = CONFIG_SCOPE_SYSTEM;
} else if (opts->use_local_config) {
- opts->source.file = opts->file_to_free = git_pathdup("config");
+ opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config");
opts->source.scope = CONFIG_SCOPE_LOCAL;
} else if (opts->use_worktree_config) {
struct worktree **worktrees = get_worktrees();
if (the_repository->repository_format_worktree_config)
opts->source.file = opts->file_to_free =
- git_pathdup("config.worktree");
+ repo_git_path(the_repository, "config.worktree");
else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple "
"working trees unless the config\n"
@@ -790,7 +790,7 @@ static void location_options_init(struct config_location_options *opts,
"section in \"git help worktree\" for details"));
else
opts->source.file = opts->file_to_free =
- git_pathdup("config");
+ repo_git_path(the_repository, "config");
opts->source.scope = CONFIG_SCOPE_LOCAL;
free_worktrees(worktrees);
} else if (opts->source.file) {
@@ -1087,7 +1087,7 @@ static int show_editor(struct config_location_options *opts)
git_config(git_default_config, NULL);
config_file = opts->source.file ?
xstrdup(opts->source.file) :
- git_pathdup("config");
+ repo_git_path(the_repository, "config");
if (opts->use_global_config) {
int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd >= 0) {
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 03a8bb92a9..41cd00066c 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -12,8 +12,6 @@
* Copyright (C) 2016 Johannes Schindelin
*/
-#define USE_THE_REPOSITORY_VARIABLE
-
#include "builtin.h"
#include "abspath.h"
@@ -36,18 +34,27 @@
#include "entry.h"
#include "setup.h"
-static int trust_exit_code;
-
static const char *const builtin_difftool_usage[] = {
N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
NULL
};
+struct difftool_options {
+ int has_symlinks;
+ int symlinks;
+ int trust_exit_code;
+};
+
static int difftool_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
+ struct difftool_options *dt_options = (struct difftool_options *)cb;
if (!strcmp(var, "difftool.trustexitcode")) {
- trust_exit_code = git_config_bool(var, value);
+ dt_options->trust_exit_code = git_config_bool(var, value);
+ return 0;
+ }
+ if (!strcmp(var, "core.symlinks")) {
+ dt_options->has_symlinks = git_config_bool(var, value);
return 0;
}
@@ -63,7 +70,8 @@ static int print_tool_help(void)
return run_command(&cmd);
}
-static int parse_index_info(char *p, int *mode1, int *mode2,
+static int parse_index_info(struct repository *repo,
+ char *p, int *mode1, int *mode2,
struct object_id *oid1, struct object_id *oid2,
char *status)
{
@@ -75,11 +83,11 @@ static int parse_index_info(char *p, int *mode1, int *mode2,
*mode2 = (int)strtol(p + 1, &p, 8);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
- if (parse_oid_hex(++p, oid1, (const char **)&p))
+ if (parse_oid_hex_algop(++p, oid1, (const char **)&p, repo->hash_algo))
return error("expected object ID, got '%s'", p);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
- if (parse_oid_hex(++p, oid2, (const char **)&p))
+ if (parse_oid_hex_algop(++p, oid2, (const char **)&p, repo->hash_algo))
return error("expected object ID, got '%s'", p);
if (*p != ' ')
return error("expected ' ', got '%c'", *p);
@@ -106,7 +114,8 @@ static void add_path(struct strbuf *buf, size_t base_len, const char *path)
/*
* Determine whether we can simply reuse the file in the worktree.
*/
-static int use_wt_file(const char *workdir, const char *name,
+static int use_wt_file(struct repository *repo,
+ const char *workdir, const char *name,
struct object_id *oid)
{
struct strbuf buf = STRBUF_INIT;
@@ -121,7 +130,7 @@ static int use_wt_file(const char *workdir, const char *name,
int fd = open(buf.buf, O_RDONLY);
if (fd >= 0 &&
- !index_fd(the_repository->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
+ !index_fd(repo->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
if (is_null_oid(oid)) {
oidcpy(oid, &wt_oid);
use = 1;
@@ -212,13 +221,14 @@ static int path_entry_cmp(const void *cmp_data UNUSED,
return strcmp(a->path, key ? key : b->path);
}
-static void changed_files(struct hashmap *result, const char *index_path,
+static void changed_files(struct repository *repo,
+ struct hashmap *result, const char *index_path,
const char *workdir)
{
struct child_process update_index = CHILD_PROCESS_INIT;
struct child_process diff_files = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT;
- const char *git_dir = absolute_path(repo_get_git_dir(the_repository));
+ const char *git_dir = absolute_path(repo_get_git_dir(repo));
FILE *fp;
strvec_pushl(&update_index.args,
@@ -291,13 +301,15 @@ static int ensure_leading_directories(char *path)
* to compare the readlink(2) result as text, even on a filesystem that is
* capable of doing a symbolic link.
*/
-static char *get_symlink(const struct object_id *oid, const char *path)
+static char *get_symlink(struct repository *repo,
+ struct difftool_options *dt_options,
+ const struct object_id *oid, const char *path)
{
char *data;
if (is_null_oid(oid)) {
/* The symlink is unknown to Git so read from the filesystem */
struct strbuf link = STRBUF_INIT;
- if (has_symlinks) {
+ if (dt_options->has_symlinks) {
if (strbuf_readlink(&link, path, strlen(path)))
die(_("could not read symlink %s"), path);
} else if (strbuf_read_file(&link, path, 128))
@@ -307,8 +319,7 @@ static char *get_symlink(const struct object_id *oid, const char *path)
} else {
enum object_type type;
unsigned long size;
- data = repo_read_object_file(the_repository, oid, &type,
- &size);
+ data = repo_read_object_file(repo, oid, &type, &size);
if (!data)
die(_("could not read object %s for symlink %s"),
oid_to_hex(oid), path);
@@ -355,7 +366,9 @@ static void write_standin_files(struct pair_entry *entry,
write_file_in_directory(rdir, rdir_len, entry->path, entry->right);
}
-static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
+static int run_dir_diff(struct repository *repo,
+ struct difftool_options *dt_options,
+ const char *extcmd, const char *prefix,
struct child_process *child)
{
struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT;
@@ -375,7 +388,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL);
struct hashmap_iter iter;
struct pair_entry *entry;
- struct index_state wtindex = INDEX_STATE_INIT(the_repository);
+ struct index_state wtindex = INDEX_STATE_INIT(repo);
struct checkout lstate, rstate;
int err = 0;
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -383,7 +396,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct hashmap tmp_modified = HASHMAP_INIT(path_entry_cmp, NULL);
int indices_loaded = 0;
- workdir = repo_get_work_tree(the_repository);
+ workdir = repo_get_work_tree(repo);
/* Setup temp directories */
tmp = getenv("TMPDIR");
@@ -438,8 +451,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
"not supported in\n"
"directory diff mode ('-d' and '--dir-diff')."));
- if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid,
- &status))
+ if (parse_index_info(repo, info.buf, &lmode, &rmode, &loid, &roid, &status))
break;
if (strbuf_getline_nul(&lpath, fp))
break;
@@ -469,13 +481,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
}
if (S_ISLNK(lmode)) {
- char *content = get_symlink(&loid, src_path);
+ char *content = get_symlink(repo, dt_options, &loid, src_path);
add_left_or_right(&symlinks2, src_path, content, 0);
free(content);
}
if (S_ISLNK(rmode)) {
- char *content = get_symlink(&roid, dst_path);
+ char *content = get_symlink(repo, dt_options, &roid, dst_path);
add_left_or_right(&symlinks2, dst_path, content, 1);
free(content);
}
@@ -500,7 +512,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
}
hashmap_add(&working_tree_dups, &entry->entry);
- if (!use_wt_file(workdir, dst_path, &roid)) {
+ if (!use_wt_file(repo, workdir, dst_path, &roid)) {
if (checkout_path(rmode, &roid, dst_path,
&rstate)) {
ret = error("could not write '%s'",
@@ -528,7 +540,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
goto finish;
}
add_path(&wtdir, wtdir_len, dst_path);
- if (symlinks) {
+ if (dt_options->symlinks) {
if (symlink(wtdir.buf, rdir.buf)) {
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
goto finish;
@@ -614,7 +626,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
if (lstat(rdir.buf, &st))
continue;
- if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
+ if ((dt_options->symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
continue;
if (!indices_loaded) {
@@ -626,9 +638,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
ret = error("could not write %s", buf.buf);
goto finish;
}
- changed_files(&wt_modified, buf.buf, workdir);
+ changed_files(repo, &wt_modified, buf.buf, workdir);
strbuf_setlen(&rdir, rdir_len);
- changed_files(&tmp_modified, buf.buf, rdir.buf);
+ changed_files(repo, &tmp_modified, buf.buf, rdir.buf);
add_path(&rdir, rdir_len, name);
indices_loaded = 1;
}
@@ -702,11 +714,15 @@ static int run_file_diff(int prompt, const char *prefix,
int cmd_difftool(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
- int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0,
- tool_help = 0, no_index = 0;
+ int use_gui_tool = -1, dir_diff = 0, prompt = -1, tool_help = 0, no_index = 0;
static char *difftool_cmd = NULL, *extcmd = NULL;
+ struct difftool_options dt_options = {
+ .has_symlinks = 1,
+ .symlinks = 1,
+ .trust_exit_code = 0
+ };
struct option builtin_difftool_options[] = {
OPT_BOOL('g', "gui", &use_gui_tool,
N_("use `diff.guitool` instead of `diff.tool`")),
@@ -717,14 +733,14 @@ int cmd_difftool(int argc,
0, PARSE_OPT_NONEG),
OPT_SET_INT_F(0, "prompt", &prompt, NULL,
1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN),
- OPT_BOOL(0, "symlinks", &symlinks,
+ OPT_BOOL(0, "symlinks", &dt_options.symlinks,
N_("use symlinks in dir-diff mode")),
OPT_STRING('t', "tool", &difftool_cmd, N_("tool"),
N_("use the specified diff tool")),
OPT_BOOL(0, "tool-help", &tool_help,
N_("print a list of diff tools that may be used with "
"`--tool`")),
- OPT_BOOL(0, "trust-exit-code", &trust_exit_code,
+ OPT_BOOL(0, "trust-exit-code", &dt_options.trust_exit_code,
N_("make 'git-difftool' exit when an invoked diff "
"tool returns a non-zero exit code")),
OPT_STRING('x', "extcmd", &extcmd, N_("command"),
@@ -734,8 +750,9 @@ int cmd_difftool(int argc,
};
struct child_process child = CHILD_PROCESS_INIT;
- git_config(difftool_config, NULL);
- symlinks = has_symlinks;
+ if (repo)
+ repo_config(repo, difftool_config, &dt_options);
+ dt_options.symlinks = dt_options.has_symlinks;
argc = parse_options(argc, argv, prefix, builtin_difftool_options,
builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN_OPT |
@@ -749,8 +766,8 @@ int cmd_difftool(int argc,
if (!no_index){
setup_work_tree();
- setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1);
- setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1);
+ setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1);
+ setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1);
} else if (dir_diff)
die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index");
@@ -783,7 +800,7 @@ int cmd_difftool(int argc,
}
setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE",
- trust_exit_code ? "true" : "false", 1);
+ dt_options.trust_exit_code ? "true" : "false", 1);
/*
* In directory diff mode, 'git-difftool--helper' is called once
@@ -799,6 +816,6 @@ int cmd_difftool(int argc,
strvec_pushv(&child.args, argv);
if (dir_diff)
- return run_dir_diff(extcmd, symlinks, prefix, &child);
+ return run_dir_diff(repo, &dt_options, extcmd, prefix, &child);
return run_file_diff(prompt, prefix, &child);
}
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index d6a368a566..397a6f46ad 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -328,7 +328,7 @@ static void write_branch_report(FILE *rpt, struct branch *b)
static void write_crash_report(const char *err)
{
- char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
+ char *loc = repo_git_path(the_repository, "fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
FILE *rpt = fopen(loc, "w");
struct branch *b;
unsigned long lu;
@@ -3280,7 +3280,7 @@ static char* make_fast_import_path(const char *path)
{
if (!relative_marks_paths || is_absolute_path(path))
return prefix_filename(global_prefix, path);
- return git_pathdup("info/fast-import/%s", path);
+ return repo_git_path(the_repository, "info/fast-import/%s", path);
}
static void option_import_marks(const char *marks,
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fe2b26c74a..1c740d5aac 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -1617,13 +1617,13 @@ static void report_set_head(const char *remote, const char *head_name,
strbuf_release(&buf_prefix);
}
-static int set_head(const struct ref *remote_refs, int follow_remote_head,
- const char *no_warn_branch)
+static int set_head(const struct ref *remote_refs, struct remote *remote)
{
- int result = 0, create_only, is_bare, was_detached;
+ int result = 0, create_only, baremirror, was_detached;
struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT,
b_local_head = STRBUF_INIT;
- const char *remote = gtransport->remote->name;
+ int follow_remote_head = remote->follow_remote_head;
+ const char *no_warn_branch = remote->no_warn_branch;
char *head_name = NULL;
struct ref *ref, *matches;
struct ref *fetch_map = NULL, **fetch_map_tail = &fetch_map;
@@ -1655,17 +1655,17 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (!head_name)
goto cleanup;
- is_bare = is_bare_repository();
- create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !is_bare;
- if (is_bare) {
+ baremirror = is_bare_repository() && remote->mirror;
+ create_only = follow_remote_head == FOLLOW_REMOTE_ALWAYS ? 0 : !baremirror;
+ if (baremirror) {
strbuf_addstr(&b_head, "HEAD");
strbuf_addf(&b_remote_head, "refs/heads/%s", head_name);
} else {
- strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote);
- strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote, head_name);
+ strbuf_addf(&b_head, "refs/remotes/%s/HEAD", remote->name);
+ strbuf_addf(&b_remote_head, "refs/remotes/%s/%s", remote->name, head_name);
}
/* make sure it's valid */
- if (!is_bare && !refs_ref_exists(refs, b_remote_head.buf)) {
+ if (!baremirror && !refs_ref_exists(refs, b_remote_head.buf)) {
result = 1;
goto cleanup;
}
@@ -1678,7 +1678,7 @@ static int set_head(const struct ref *remote_refs, int follow_remote_head,
if (verbosity >= 0 &&
follow_remote_head == FOLLOW_REMOTE_WARN &&
(!no_warn_branch || strcmp(no_warn_branch, head_name)))
- report_set_head(remote, head_name, &b_local_head, was_detached);
+ report_set_head(remote->name, head_name, &b_local_head, was_detached);
cleanup:
free(head_name);
@@ -1924,8 +1924,7 @@ static int do_fetch(struct transport *transport,
"you need to specify exactly one branch with the --set-upstream option"));
}
}
- if (set_head(remote_refs, transport->remote->follow_remote_head,
- transport->remote->no_warn_branch))
+ if (set_head(remote_refs, transport->remote))
;
/*
* Way too many cases where this can go wrong
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 7a4dcb0716..eea1d43647 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -326,7 +326,7 @@ static void check_unreachable_object(struct object *obj)
printable_type(&obj->oid, obj->type),
describe_object(&obj->oid));
if (write_lost_and_found) {
- char *filename = git_pathdup("lost-found/%s/%s",
+ char *filename = repo_git_path(the_repository, "lost-found/%s/%s",
obj->type == OBJ_COMMIT ? "commit" : "other",
describe_object(&obj->oid));
FILE *f;
@@ -1057,7 +1057,7 @@ int cmd_fsck(int argc,
struct worktree *wt = *p;
struct index_state istate =
INDEX_STATE_INIT(the_repository);
- char *path;
+ char *path, *wt_gitdir;
/*
* Make a copy since the buffer is reusable
@@ -1065,9 +1065,13 @@ int cmd_fsck(int argc,
* while we're examining the index.
*/
path = xstrdup(worktree_git_path(the_repository, wt, "index"));
- read_index_from(&istate, path, get_worktree_git_dir(wt));
+ wt_gitdir = get_worktree_git_dir(wt);
+
+ read_index_from(&istate, path, wt_gitdir);
fsck_index(&istate, path, wt->is_current);
+
discard_index(&istate);
+ free(wt_gitdir);
free(path);
}
free_worktrees(worktrees);
diff --git a/builtin/gc.c b/builtin/gc.c
index 409d454a4b..99431fd467 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -99,9 +99,11 @@ static void process_log_file(void)
/* There was some error recorded in the lock file */
commit_lock_file(&log_lock);
} else {
+ char *path = repo_git_path(the_repository, "gc.log");
/* No error, clean up any old gc.log */
- unlink(git_path("gc.log"));
+ unlink(path);
rollback_lock_file(&log_lock);
+ free(path);
}
}
@@ -300,8 +302,11 @@ static int too_many_loose_objects(struct gc_config *cfg)
int num_loose = 0;
int needed = 0;
const unsigned hexsz_loose = the_hash_algo->hexsz - 2;
+ char *path;
- dir = opendir(git_path("objects/17"));
+ path = repo_git_path(the_repository, "objects/17");
+ dir = opendir(path);
+ free(path);
if (!dir)
return 0;
@@ -550,7 +555,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
if (xgethostname(my_host, sizeof(my_host)))
xsnprintf(my_host, sizeof(my_host), "unknown");
- pidfile_path = git_pathdup("gc.pid");
+ pidfile_path = repo_git_path(the_repository, "gc.pid");
fd = hold_lock_file_for_update(&lock, pidfile_path,
LOCK_DIE_ON_ERROR);
if (!force) {
@@ -611,7 +616,7 @@ static int report_last_gc_error(void)
int ret = 0;
ssize_t len;
struct stat st;
- char *gc_log_path = git_pathdup("gc.log");
+ char *gc_log_path = repo_git_path(the_repository, "gc.log");
if (stat(gc_log_path, &st)) {
if (errno == ENOENT)
@@ -826,11 +831,12 @@ struct repository *repo UNUSED)
}
if (daemonized) {
- hold_lock_file_for_update(&log_lock,
- git_path("gc.log"),
+ char *path = repo_git_path(the_repository, "gc.log");
+ hold_lock_file_for_update(&log_lock, path,
LOCK_DIE_ON_ERROR);
dup2(get_lock_file_fd(&log_lock), 2);
atexit(process_log_file_at_exit);
+ free(path);
}
gc_before_repack(&opts, &cfg);
@@ -892,8 +898,11 @@ struct repository *repo UNUSED)
warning(_("There are too many unreachable loose objects; "
"run 'git prune' to remove them."));
- if (!daemonized)
- unlink(git_path("gc.log"));
+ if (!daemonized) {
+ char *path = repo_git_path(the_repository, "gc.log");
+ unlink(path);
+ free(path);
+ }
out:
gc_config_release(&cfg);
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 096f96b9c4..196dccdd77 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -132,8 +132,8 @@ int cmd_init_db(int argc,
* and we know shared_repository should always be 0;
* but just in case we play safe.
*/
- saved = get_shared_repository();
- set_shared_repository(0);
+ saved = repo_settings_get_shared_repository(the_repository);
+ repo_settings_set_shared_repository(the_repository, 0);
switch (safe_create_leading_directories_const(argv[0])) {
case SCLD_OK:
case SCLD_PERMS:
@@ -145,7 +145,7 @@ int cmd_init_db(int argc,
die_errno(_("cannot mkdir %s"), argv[0]);
break;
}
- set_shared_repository(saved);
+ repo_settings_set_shared_repository(the_repository, saved);
if (mkdir(argv[0], 0777) < 0)
die_errno(_("cannot mkdir %s"), argv[0]);
mkdir_tried = 1;
@@ -175,7 +175,7 @@ int cmd_init_db(int argc,
}
if (init_shared_repository != -1)
- set_shared_repository(init_shared_repository);
+ repo_settings_set_shared_repository(the_repository, init_shared_repository);
/*
* GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
diff --git a/builtin/log.c b/builtin/log.c
index e41f88945e..04a6ef97bc 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -2309,8 +2309,8 @@ int cmd_format_patch(int argc,
* We consider <outdir> as 'outside of gitdir', therefore avoid
* applying adjust_shared_perm in s-c-l-d.
*/
- saved = get_shared_repository();
- set_shared_repository(0);
+ saved = repo_settings_get_shared_repository(the_repository);
+ repo_settings_set_shared_repository(the_repository, 0);
switch (safe_create_leading_directories_const(output_directory)) {
case SCLD_OK:
case SCLD_EXISTS:
@@ -2319,7 +2319,7 @@ int cmd_format_patch(int argc,
die(_("could not create leading directories "
"of '%s'"), output_directory);
}
- set_shared_repository(saved);
+ repo_settings_set_shared_repository(the_repository, saved);
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
die_errno(_("could not create directory '%s'"),
output_directory);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 9a6c8b4e4c..3ec7127b3a 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -18,6 +18,7 @@
#include "tree.h"
#include "config.h"
#include "strvec.h"
+#include "write-or-die.h"
static int line_termination = '\n';
@@ -575,7 +576,7 @@ int cmd_merge_tree(int argc,
};
/* Init merge options */
- init_ui_merge_options(&o.merge_options, the_repository);
+ init_basic_merge_options(&o.merge_options, the_repository);
/* Parse arguments */
original_argc = argc - 1; /* ignoring argv[0] */
@@ -600,7 +601,6 @@ int cmd_merge_tree(int argc,
line_termination = '\0';
while (strbuf_getline_lf(&buf, stdin) != EOF) {
struct strbuf **split;
- int result;
const char *input_merge_base = NULL;
split = strbuf_split(&buf, ' ');
@@ -617,15 +617,14 @@ int cmd_merge_tree(int argc,
if (input_merge_base && split[2] && split[3] && !split[4]) {
strbuf_rtrim(split[2]);
strbuf_rtrim(split[3]);
- result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
+ real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
} else if (!input_merge_base && !split[2]) {
- result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
+ real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
} else {
die(_("malformed input line: '%s'."), buf.buf);
}
+ maybe_flush_or_die(stdout, "stdout");
- if (result < 0)
- die(_("merging cannot continue; got unclean result of %d"), result);
strbuf_list_free(split);
}
strbuf_release(&buf);
diff --git a/builtin/notes.c b/builtin/notes.c
index d051abf6df..ff61ec5f2d 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -197,7 +197,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data *
struct strbuf buf = STRBUF_INIT;
/* write the template message before editing: */
- d->edit_path = git_pathdup("NOTES_EDITMSG");
+ d->edit_path = repo_git_path(the_repository, "NOTES_EDITMSG");
fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (d->msg_nr)
@@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix,
else { /* Merge has unresolved conflicts */
struct worktree **worktrees;
const struct worktree *wt;
+ char *path;
+
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
refs_update_ref(get_main_ref_store(the_repository), msg.buf,
"NOTES_MERGE_PARTIAL", &result_oid, NULL,
@@ -994,10 +996,13 @@ static int merge(int argc, const char **argv, const char *prefix,
if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL))
die(_("failed to store link to current notes ref (%s)"),
notes_ref);
+
+ path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE);
fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
"and commit the result with 'git notes merge --commit', "
"or abort the merge with 'git notes merge --abort'.\n"),
- git_path(NOTES_MERGE_WORKTREE));
+ path);
+ free(path);
}
free_notes(t);
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 6c9eaf3788..d4715ed35d 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts)
return run_command(&am);
}
- rebased_patches = xstrdup(git_path("rebased-patches"));
+ rebased_patches = repo_git_path(the_repository, "rebased-patches");
format_patch.out = open(rebased_patches,
O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (format_patch.out < 0) {
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 129305700c..7b28fc9df6 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash,
static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
{
- const char *retval, *git_dir;
+ const char *retval;
+ char *git_dir;
struct strvec env = STRVEC_INIT;
int invoked_hook;
@@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w
retval = push_to_deploy(sha1, &env, worktree->path);
strvec_clear(&env);
+ free(git_dir);
return retval;
}
diff --git a/builtin/remote.c b/builtin/remote.c
index 816d482340..1b7aad8838 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -644,9 +644,11 @@ static int migrate_file(struct remote *remote)
git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0);
#ifndef WITH_BREAKING_CHANGES
if (remote->origin == REMOTE_REMOTES)
- unlink_or_warn(git_path("remotes/%s", remote->name));
+ unlink_or_warn(repo_git_path_replace(the_repository, &buf,
+ "remotes/%s", remote->name));
else if (remote->origin == REMOTE_BRANCHES)
- unlink_or_warn(git_path("branches/%s", remote->name));
+ unlink_or_warn(repo_git_path_replace(the_repository, &buf,
+ "branches/%s", remote->name));
#endif /* WITH_BREAKING_CHANGES */
strbuf_release(&buf);
diff --git a/builtin/replace.c b/builtin/replace.c
index a4eaadff91..15ec0922ce 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -345,7 +345,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw)
}
strbuf_release(&ref);
- tmpfile = git_pathdup("REPLACE_EDITOBJ");
+ tmpfile = repo_git_path(the_repository, "REPLACE_EDITOBJ");
if (export_object(&old_oid, type, raw, tmpfile)) {
free(tmpfile);
return -1;
diff --git a/builtin/replay.c b/builtin/replay.c
index 1afc6d1ee0..032c172b65 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -163,9 +163,10 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
get_ref_information(cmd_info, &rinfo);
if (!rinfo.positive_refexprs)
die(_("need some commits to replay"));
- if (onto_name && *advance_name)
- die(_("--onto and --advance are incompatible"));
- else if (onto_name) {
+
+ die_for_incompatible_opt2(!!onto_name, "--onto",
+ !!*advance_name, "--advance");
+ if (onto_name) {
*onto = peel_committish(onto_name);
if (rinfo.positive_refexprs <
strset_get_size(&rinfo.positive_refs))
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 41127e24e5..1312e79d89 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -4,9 +4,9 @@
#include "config.h"
#include "gettext.h"
#include "parse-options.h"
-
-#include "string-list.h"
#include "rerere.h"
+#include "strbuf.h"
+#include "string-list.h"
#include "xdiff/xdiff.h"
#include "xdiff-interface.h"
#include "pathspec.h"
@@ -112,15 +112,18 @@ int cmd_rerere(int argc,
merge_rr.items[i].util = NULL;
}
} else if (!strcmp(argv[0], "diff")) {
+ struct strbuf buf = STRBUF_INIT;
if (setup_rerere(the_repository, &merge_rr,
flags | RERERE_READONLY) < 0)
return 0;
for (size_t i = 0; i < merge_rr.nr; i++) {
const char *path = merge_rr.items[i].string;
const struct rerere_id *id = merge_rr.items[i].util;
- if (diff_two(rerere_path(id, "preimage"), path, path, path))
- die(_("unable to generate diff for '%s'"), rerere_path(id, NULL));
+ if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path))
+ die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL));
}
+
+ strbuf_release(&buf);
} else
usage_with_options(rerere_usage, options);
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index beb8c2529d..bb26bee0d4 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -22,7 +22,10 @@
#include "progress.h"
#include "reflog-walk.h"
#include "oidset.h"
+#include "oidmap.h"
#include "packfile.h"
+#include "quote.h"
+#include "strbuf.h"
static const char rev_list_usage[] =
"git rev-list [<options>] <commit>... [--] [<path>...]\n"
@@ -73,11 +76,17 @@ static unsigned progress_counter;
static struct oidset omitted_objects;
static int arg_print_omitted; /* print objects omitted by filter */
-static struct oidset missing_objects;
+struct missing_objects_map_entry {
+ struct oidmap_entry entry;
+ const char *path;
+ unsigned type;
+};
+static struct oidmap missing_objects;
enum missing_action {
MA_ERROR = 0, /* fail if any missing objects are encountered */
MA_ALLOW_ANY, /* silently allow ALL missing objects */
MA_PRINT, /* print ALL missing objects in special section */
+ MA_PRINT_INFO, /* same as MA_PRINT but also prints missing object info */
MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
};
static enum missing_action arg_missing_action;
@@ -101,7 +110,49 @@ static off_t get_object_disk_usage(struct object *obj)
return size;
}
-static inline void finish_object__ma(struct object *obj)
+static void add_missing_object_entry(struct object_id *oid, const char *path,
+ unsigned type)
+{
+ struct missing_objects_map_entry *entry;
+
+ if (oidmap_get(&missing_objects, oid))
+ return;
+
+ CALLOC_ARRAY(entry, 1);
+ entry->entry.oid = *oid;
+ entry->type = type;
+ if (path)
+ entry->path = xstrdup(path);
+ oidmap_put(&missing_objects, entry);
+}
+
+static void print_missing_object(struct missing_objects_map_entry *entry,
+ int print_missing_info)
+{
+ struct strbuf sb = STRBUF_INIT;
+
+ if (!print_missing_info) {
+ printf("?%s\n", oid_to_hex(&entry->entry.oid));
+ return;
+ }
+
+ if (entry->path && *entry->path) {
+ struct strbuf path = STRBUF_INIT;
+
+ strbuf_addstr(&sb, " path=");
+ quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
+ strbuf_addbuf(&sb, &path);
+
+ strbuf_release(&path);
+ }
+ if (entry->type)
+ strbuf_addf(&sb, " type=%s", type_name(entry->type));
+
+ printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf);
+ strbuf_release(&sb);
+}
+
+static inline void finish_object__ma(struct object *obj, const char *name)
{
/*
* Whether or not we try to dynamically fetch missing objects
@@ -119,7 +170,8 @@ static inline void finish_object__ma(struct object *obj)
return;
case MA_PRINT:
- oidset_insert(&missing_objects, &obj->oid);
+ case MA_PRINT_INFO:
+ add_missing_object_entry(&obj->oid, name, obj->type);
return;
case MA_ALLOW_PROMISOR:
@@ -152,7 +204,7 @@ static void show_commit(struct commit *commit, void *data)
if (revs->do_not_die_on_missing_objects &&
oidset_contains(&revs->missing_commits, &commit->object.oid)) {
- finish_object__ma(&commit->object);
+ finish_object__ma(&commit->object, NULL);
return;
}
@@ -268,12 +320,11 @@ static void show_commit(struct commit *commit, void *data)
finish_commit(commit);
}
-static int finish_object(struct object *obj, const char *name UNUSED,
- void *cb_data)
+static int finish_object(struct object *obj, const char *name, void *cb_data)
{
struct rev_list_info *info = cb_data;
if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
- finish_object__ma(obj);
+ finish_object__ma(obj, name);
return 1;
}
if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
@@ -414,6 +465,12 @@ static inline int parse_missing_action_value(const char *value)
return 1;
}
+ if (!strcmp(value, "print-info")) {
+ arg_missing_action = MA_PRINT_INFO;
+ fetch_if_missing = 0;
+ return 1;
+ }
+
if (!strcmp(value, "allow-promisor")) {
arg_missing_action = MA_ALLOW_PROMISOR;
fetch_if_missing = 0;
@@ -781,10 +838,18 @@ int cmd_rev_list(int argc,
if (arg_print_omitted)
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
- if (arg_missing_action == MA_PRINT) {
- oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
+ if (arg_missing_action == MA_PRINT ||
+ arg_missing_action == MA_PRINT_INFO) {
+ struct oidset_iter iter;
+ struct object_id *oid;
+
+ oidmap_init(&missing_objects, DEFAULT_OIDSET_SIZE);
+ oidset_iter_init(&revs.missing_commits, &iter);
+
/* Add missing tips */
- oidset_insert_from_set(&missing_objects, &revs.missing_commits);
+ while ((oid = oidset_iter_next(&iter)))
+ add_missing_object_entry(oid, NULL, 0);
+
oidset_clear(&revs.missing_commits);
}
@@ -800,13 +865,20 @@ int cmd_rev_list(int argc,
printf("~%s\n", oid_to_hex(oid));
oidset_clear(&omitted_objects);
}
- if (arg_missing_action == MA_PRINT) {
- struct oidset_iter iter;
- struct object_id *oid;
- oidset_iter_init(&missing_objects, &iter);
- while ((oid = oidset_iter_next(&iter)))
- printf("?%s\n", oid_to_hex(oid));
- oidset_clear(&missing_objects);
+ if (arg_missing_action == MA_PRINT ||
+ arg_missing_action == MA_PRINT_INFO) {
+ struct missing_objects_map_entry *entry;
+ struct oidmap_iter iter;
+
+ oidmap_iter_init(&missing_objects, &iter);
+
+ while ((entry = oidmap_iter_next(&iter))) {
+ print_missing_object(entry, arg_missing_action ==
+ MA_PRINT_INFO);
+ free((void *)entry->path);
+ }
+
+ oidmap_free(&missing_objects, true);
}
stop_progress(&progress);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 428c866c05..490da33bec 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -789,8 +789,8 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--git-path")) {
if (!argv[i + 1])
die(_("--git-path requires an argument"));
- strbuf_reset(&buf);
- print_path(git_path("%s", argv[i + 1]), prefix,
+ print_path(repo_git_path_replace(the_repository, &buf,
+ "%s", argv[i + 1]), prefix,
format,
DEFAULT_RELATIVE_IF_SHARED);
i++;
@@ -1083,7 +1083,7 @@ int cmd_rev_parse(int argc,
die(_("Could not read the index"));
if (the_repository->index->split_index) {
const struct object_id *oid = &the_repository->index->split_index->base_oid;
- const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
+ const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid));
print_path(path, prefix, format, DEFAULT_RELATIVE);
}
continue;
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index f9b970f8a6..c1a8029714 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix,
remote_key = xstrfmt("remote.%s.url", default_remote);
free(default_remote);
- submodule_to_gitdir(&sb, path);
+ submodule_to_gitdir(the_repository, &sb, path);
strbuf_addstr(&sb, "/config");
if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url))
@@ -1826,7 +1826,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
- p = git_pathdup_submodule(clone_data_path, "config");
+ p = repo_submodule_path(the_repository, clone_data_path, "config");
if (!p)
die(_("could not get submodule directory for '%s'"), clone_data_path);
diff --git a/builtin/tag.c b/builtin/tag.c
index e8a344b926..d3e0943b73 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -667,7 +667,7 @@ int cmd_tag(int argc,
if (create_tag_object) {
if (force_sign_annotate && !annotate)
opt.sign = 1;
- path = git_pathdup("TAG_EDITMSG");
+ path = repo_git_path(the_repository, "TAG_EDITMSG");
create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object,
&trailer_args, path);
}
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 47a3f0bdd9..d7467290a8 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -1,4 +1,3 @@
-#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -13,7 +12,7 @@ static const char * const update_server_info_usage[] = {
int cmd_update_server_info(int argc,
const char **argv,
const char *prefix,
- struct repository *repo UNUSED)
+ struct repository *repo)
{
int force = 0;
struct option options[] = {
@@ -21,11 +20,12 @@ int cmd_update_server_info(int argc,
OPT_END()
};
- git_config(git_default_config, NULL);
+ if (repo)
+ repo_config(repo, git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options,
update_server_info_usage, 0);
if (argc > 0)
usage_with_options(update_server_info_usage, options);
- return !!update_server_info(the_repository, force);
+ return !!update_server_info(repo, force);
}
diff --git a/builtin/worktree.c b/builtin/worktree.c
index c043d4d523..48448a8355 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -151,7 +151,7 @@ static int delete_git_dir(const char *id)
struct strbuf sb = STRBUF_INIT;
int ret;
- strbuf_addstr(&sb, git_common_path("worktrees/%s", id));
+ repo_common_path_append(the_repository, &sb, "worktrees/%s", id);
ret = remove_dir_recursively(&sb, 0);
if (ret < 0 && errno == ENOTDIR)
ret = unlink(sb.buf);
@@ -163,7 +163,9 @@ static int delete_git_dir(const char *id)
static void delete_worktrees_dir_if_empty(void)
{
- rmdir(git_path("worktrees")); /* ignore failed removal */
+ char *path = repo_git_path(the_repository, "worktrees");
+ rmdir(path); /* ignore failed removal */
+ free(path);
}
static void prune_worktree(const char *id, const char *reason)
@@ -212,8 +214,13 @@ static void prune_worktrees(void)
struct strbuf reason = STRBUF_INIT;
struct strbuf main_path = STRBUF_INIT;
struct string_list kept = STRING_LIST_INIT_DUP;
- DIR *dir = opendir(git_path("worktrees"));
+ char *path;
+ DIR *dir;
struct dirent *d;
+
+ path = repo_git_path(the_repository, "worktrees");
+ dir = opendir(path);
+ free(path);
if (!dir)
return;
while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
@@ -337,7 +344,7 @@ static void check_candidate_path(const char *path,
static void copy_sparse_checkout(const char *worktree_git_dir)
{
- char *from_file = git_pathdup("info/sparse-checkout");
+ char *from_file = repo_git_path(the_repository, "info/sparse-checkout");
char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir);
if (file_exists(from_file)) {
@@ -353,7 +360,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)
static void copy_filtered_worktree_config(const char *worktree_git_dir)
{
- char *from_file = git_pathdup("config.worktree");
+ char *from_file = repo_git_path(the_repository, "config.worktree");
char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir);
if (file_exists(from_file)) {
@@ -457,7 +464,7 @@ static int add_worktree(const char *path, const char *refname,
BUG("How come '%s' becomes empty after sanitization?", sb.buf);
strbuf_reset(&sb);
name = sb_name.buf;
- git_path_buf(&sb_repo, "worktrees/%s", name);
+ repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name);
len = sb_repo.len;
if (safe_create_leading_directories_const(sb_repo.buf))
die_errno(_("could not create leading directories of '%s'"),
@@ -657,8 +664,9 @@ static int can_use_local_refs(const struct add_opts *opts)
if (!opts->quiet) {
struct strbuf path = STRBUF_INIT;
struct strbuf contents = STRBUF_INIT;
+ char *wt_gitdir = get_worktree_git_dir(NULL);
- strbuf_add_real_path(&path, get_worktree_git_dir(NULL));
+ strbuf_add_real_path(&path, wt_gitdir);
strbuf_addstr(&path, "/HEAD");
strbuf_read_file(&contents, path.buf, 64);
strbuf_stripspace(&contents, NULL);
@@ -670,6 +678,7 @@ static int can_use_local_refs(const struct add_opts *opts)
path.buf, contents.buf);
strbuf_release(&path);
strbuf_release(&contents);
+ free(wt_gitdir);
}
return 1;
}
@@ -1100,6 +1109,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
OPT_END()
};
struct worktree **worktrees, *wt;
+ char *path;
ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0);
if (ac != 1)
@@ -1120,9 +1130,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
die(_("'%s' is already locked"), av[0]);
}
- write_file(git_common_path("worktrees/%s/locked", wt->id),
- "%s", reason);
+ path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id);
+ write_file(path, "%s", reason);
+
free_worktrees(worktrees);
+ free(path);
return 0;
}
@@ -1133,6 +1145,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
OPT_END()
};
struct worktree **worktrees, *wt;
+ char *path;
int ret;
ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0);
@@ -1147,8 +1160,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
die(_("The main working tree cannot be locked or unlocked"));
if (!worktree_lock_reason(wt))
die(_("'%s' is not locked"), av[0]);
- ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
+
+ path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id);
+ ret = unlink_or_warn(path);
+
free_worktrees(worktrees);
+ free(path);
return ret;
}
@@ -1157,6 +1174,9 @@ static void validate_no_submodules(const struct worktree *wt)
struct index_state istate = INDEX_STATE_INIT(the_repository);
struct strbuf path = STRBUF_INIT;
int i, found_submodules = 0;
+ char *wt_gitdir;
+
+ wt_gitdir = get_worktree_git_dir(wt);
if (is_directory(worktree_git_path(the_repository, wt, "modules"))) {
/*
@@ -1166,7 +1186,7 @@ static void validate_no_submodules(const struct worktree *wt)
*/
found_submodules = 1;
} else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"),
- get_worktree_git_dir(wt)) > 0) {
+ wt_gitdir) > 0) {
for (i = 0; i < istate.cache_nr; i++) {
struct cache_entry *ce = istate.cache[i];
int err;
@@ -1185,6 +1205,7 @@ static void validate_no_submodules(const struct worktree *wt)
}
discard_index(&istate);
strbuf_release(&path);
+ free(wt_gitdir);
if (found_submodules)
die(_("working trees containing submodules cannot be moved or removed"));