summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/branch.c5
-rw-r--r--builtin/bundle.c8
-rw-r--r--builtin/checkout.c28
-rw-r--r--builtin/clone.c50
-rw-r--r--builtin/config.c4
-rw-r--r--builtin/describe.c62
-rw-r--r--builtin/for-each-ref.c5
-rw-r--r--builtin/grep.c64
-rw-r--r--builtin/hash-object.c10
-rw-r--r--builtin/index-pack.c31
-rw-r--r--builtin/log.c3
-rw-r--r--builtin/ls-files.c41
-rw-r--r--builtin/mailinfo.c11
-rw-r--r--builtin/merge-file.c18
-rw-r--r--builtin/merge.c59
-rw-r--r--builtin/pack-objects.c12
-rw-r--r--builtin/read-tree.c29
-rw-r--r--builtin/receive-pack.c15
-rw-r--r--builtin/rev-parse.c115
-rw-r--r--builtin/send-pack.c5
-rw-r--r--builtin/shortlog.c1
-rw-r--r--builtin/submodule--helper.c90
-rw-r--r--builtin/tag.c27
-rw-r--r--builtin/worktree.c5
24 files changed, 417 insertions, 281 deletions
diff --git a/builtin/branch.c b/builtin/branch.c
index 52688f2e1b..0552c42ad1 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -562,7 +562,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"),
FILTER_REFS_REMOTES),
OPT_CONTAINS(&filter.with_commit, N_("print only branches that contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only branches that don't contain the commit")),
OPT_WITH(&filter.with_commit, N_("print only branches that contain the commit")),
+ OPT_WITHOUT(&filter.no_commit, N_("print only branches that don't contain the commit")),
OPT__ABBREV(&filter.abbrev),
OPT_GROUP(N_("Specific git-branch actions:")),
@@ -618,7 +620,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
list = 1;
- if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr)
+ if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || filter.points_at.nr ||
+ filter.no_commit)
list = 1;
if (!!delete + !!rename + !!new_upstream +
diff --git a/builtin/bundle.c b/builtin/bundle.c
index 4883a435a9..d0de59b94f 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -20,21 +20,15 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
struct bundle_header header;
const char *cmd, *bundle_file;
int bundle_fd = -1;
- char buffer[PATH_MAX];
if (argc < 3)
usage(builtin_bundle_usage);
cmd = argv[1];
- bundle_file = argv[2];
+ bundle_file = prefix_filename(prefix, argv[2]);
argc -= 2;
argv += 2;
- if (prefix && bundle_file[0] != '/') {
- snprintf(buffer, sizeof(buffer), "%s/%s", prefix, bundle_file);
- bundle_file = buffer;
- }
-
memset(&header, 0, sizeof(header));
if (strcmp(cmd, "create") && (bundle_fd =
read_bundle_header(bundle_file, &header)) < 0)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 81f07c3ef2..3ecc47bec0 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -21,12 +21,31 @@
#include "submodule-config.h"
#include "submodule.h"
+static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
+
static const char * const checkout_usage[] = {
N_("git checkout [<options>] <branch>"),
N_("git checkout [<options>] [<branch>] -- <file>..."),
NULL,
};
+static int option_parse_recurse_submodules(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset) {
+ recurse_submodules = RECURSE_SUBMODULES_OFF;
+ return 0;
+ }
+ if (arg)
+ recurse_submodules =
+ parse_update_recurse_submodules_arg(opt->long_name,
+ arg);
+ else
+ recurse_submodules = RECURSE_SUBMODULES_ON;
+
+ return 0;
+}
+
struct checkout_opts {
int patch_mode;
int quiet;
@@ -1163,6 +1182,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
N_("second guess 'git checkout <no-such-branch>'")),
OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
N_("do not check if another worktree is holding the given ref")),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+ "checkout", "control recursive updating of submodules",
+ PARSE_OPT_OPTARG, option_parse_recurse_submodules },
OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
OPT_END(),
};
@@ -1193,6 +1215,12 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
}
+ if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
+ git_config(submodule_config, NULL);
+ if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT)
+ set_config_update_recurse_submodules(recurse_submodules);
+ }
+
if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
die(_("-b, -B and --orphan are mutually exclusive"));
diff --git a/builtin/clone.c b/builtin/clone.c
index b4c929bb8a..de85b85254 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -39,7 +39,7 @@ static const char * const builtin_clone_usage[] = {
};
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
-static int option_local = -1, option_no_hardlinks, option_shared, option_recursive;
+static int option_local = -1, option_no_hardlinks, option_shared;
static int option_shallow_submodules;
static int deepen;
static char *option_template, *option_depth, *option_since;
@@ -56,6 +56,21 @@ 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 int recurse_submodules_cb(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset)
+ string_list_clear((struct string_list *)opt->value, 0);
+ else if (arg)
+ string_list_append((struct string_list *)opt->value, arg);
+ else
+ string_list_append((struct string_list *)opt->value,
+ (const char *)opt->defval);
+
+ return 0;
+}
static struct option builtin_clone_options[] = {
OPT__VERBOSITY(&option_verbosity),
@@ -74,10 +89,13 @@ static struct option builtin_clone_options[] = {
N_("don't use local hardlinks, always copy")),
OPT_BOOL('s', "shared", &option_shared,
N_("setup as shared repository")),
- OPT_BOOL(0, "recursive", &option_recursive,
- N_("initialize submodules in the clone")),
- OPT_BOOL(0, "recurse-submodules", &option_recursive,
- N_("initialize submodules in the clone")),
+ { OPTION_CALLBACK, 0, "recursive", &option_recurse_submodules,
+ N_("pathspec"), N_("initialize submodules in the clone"),
+ PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, recurse_submodules_cb,
+ (intptr_t)"." },
+ { 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_INTEGER('j', "jobs", &max_jobs,
N_("number of submodules cloned in parallel")),
OPT_STRING(0, "template", &option_template, N_("template-directory"),
@@ -733,7 +751,7 @@ static int checkout(int submodule_progress)
err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
oid_to_hex(&oid), "1", NULL);
- if (!err && option_recursive) {
+ if (!err && (option_recurse_submodules.nr > 0)) {
struct argv_array args = ARGV_ARRAY_INIT;
argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL);
@@ -957,7 +975,25 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
fprintf(stderr, _("Cloning into '%s'...\n"), dir);
}
- if (option_recursive) {
+ if (option_recurse_submodules.nr > 0) {
+ struct string_list_item *item;
+ struct strbuf sb = STRBUF_INIT;
+
+ /* remove duplicates */
+ string_list_sort(&option_recurse_submodules);
+ string_list_remove_duplicates(&option_recurse_submodules, 0);
+
+ /*
+ * NEEDSWORK: In a multi-working-tree world, this needs to be
+ * set in the per-worktree config.
+ */
+ 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));
+ }
+
if (option_required_reference.nr &&
option_optional_reference.nr)
die(_("clone --recursive is not compatible with "
diff --git a/builtin/config.c b/builtin/config.c
index 05843a0f96..4f49a0edb9 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -527,9 +527,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
else if (given_config_source.file) {
if (!is_absolute_path(given_config_source.file) && prefix)
given_config_source.file =
- xstrdup(prefix_filename(prefix,
- strlen(prefix),
- given_config_source.file));
+ prefix_filename(prefix, given_config_source.file);
}
if (respect_includes == -1)
diff --git a/builtin/describe.c b/builtin/describe.c
index 76c18059bf..a5cd8c513f 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -9,6 +9,7 @@
#include "diff.h"
#include "hashmap.h"
#include "argv-array.h"
+#include "run-command.h"
#define SEEN (1u << 0)
#define MAX_TAGS (FLAG_BITS - 1)
@@ -31,7 +32,7 @@ static int have_util;
static struct string_list patterns = STRING_LIST_INIT_NODUP;
static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
static int always;
-static const char *dirty;
+static const char *suffix, *dirty, *broken;
/* diff-index command arguments to check if working tree is dirty. */
static const char *diff_index_args[] = {
@@ -49,7 +50,7 @@ struct commit_name {
};
static const char *prio_names[] = {
- "head", "lightweight", "annotated",
+ N_("head"), N_("lightweight"), N_("annotated"),
};
static int commit_name_cmp(const struct commit_name *cn1,
@@ -292,8 +293,8 @@ static void describe(const char *arg, int last_one)
display_name(n);
if (longformat)
show_suffix(0, n->tag ? &n->tag->tagged->oid : &oid);
- if (dirty)
- printf("%s", dirty);
+ if (suffix)
+ printf("%s", suffix);
printf("\n");
return;
}
@@ -369,8 +370,8 @@ static void describe(const char *arg, int last_one)
struct object_id *oid = &cmit->object.oid;
if (always) {
printf("%s", find_unique_abbrev(oid->hash, abbrev));
- if (dirty)
- printf("%s", dirty);
+ if (suffix)
+ printf("%s", suffix);
printf("\n");
return;
}
@@ -394,10 +395,19 @@ static void describe(const char *arg, int last_one)
free_commit_list(list);
if (debug) {
+ static int label_width = -1;
+ if (label_width < 0) {
+ int i, w;
+ for (i = 0; i < ARRAY_SIZE(prio_names); i++) {
+ w = strlen(_(prio_names[i]));
+ if (label_width < w)
+ label_width = w;
+ }
+ }
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
struct possible_tag *t = &all_matches[cur_match];
- fprintf(stderr, " %-11s %8d %s\n",
- prio_names[t->name->prio],
+ fprintf(stderr, " %-*s %8d %s\n",
+ label_width, _(prio_names[t->name->prio]),
t->depth, t->name->path);
}
fprintf(stderr, _("traversed %lu commits\n"), seen_commits);
@@ -413,8 +423,8 @@ static void describe(const char *arg, int last_one)
display_name(all_matches[0].name);
if (abbrev)
show_suffix(all_matches[0].depth, &cmit->object.oid);
- if (dirty)
- printf("%s", dirty);
+ if (suffix)
+ printf("%s", suffix);
printf("\n");
if (!last_one)
@@ -445,6 +455,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
{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"},
OPT_END(),
};
@@ -493,7 +506,28 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
die(_("No names found, cannot describe anything."));
if (argc == 0) {
- if (dirty) {
+ if (broken) {
+ struct child_process cp = CHILD_PROCESS_INIT;
+ argv_array_pushv(&cp.args, diff_index_args);
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ cp.no_stdout = 1;
+
+ if (!dirty)
+ dirty = "-dirty";
+
+ switch (run_command(&cp)) {
+ case 0:
+ suffix = NULL;
+ break;
+ case 1:
+ suffix = dirty;
+ break;
+ default:
+ /* diff-index aborted abnormally */
+ suffix = broken;
+ }
+ } else if (dirty) {
static struct lock_file index_lock;
int fd;
@@ -506,11 +540,15 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (!cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1,
diff_index_args, prefix))
- dirty = NULL;
+ suffix = NULL;
+ else
+ suffix = dirty;
}
describe("HEAD", 1);
} else if (dirty) {
die(_("--dirty is incompatible with commit-ishes"));
+ } else if (broken) {
+ die(_("--broken is incompatible with commit-ishes"));
} else {
while (argc-- > 0)
describe(*argv++, argc == 0);
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index df41fa0350..eca365bf89 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -8,8 +8,8 @@
static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [<options>] [<pattern>]"),
N_("git for-each-ref [--points-at <object>]"),
- N_("git for-each-ref [(--merged | --no-merged) [<object>]]"),
- N_("git for-each-ref [--contains [<object>]]"),
+ N_("git for-each-ref [(--merged | --no-merged) [<commit>]]"),
+ N_("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]"),
NULL
};
@@ -43,6 +43,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
OPT_MERGED(&filter, N_("print only refs that are merged")),
OPT_NO_MERGED(&filter, N_("print only refs that are not merged")),
OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_END(),
};
diff --git a/builtin/grep.c b/builtin/grep.c
index 837836fb3e..65070c52fc 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -310,10 +310,7 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
{
struct strbuf pathbuf = STRBUF_INIT;
- if (opt->relative && opt->prefix_length) {
- quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
- strbuf_insert(&pathbuf, 0, filename, tree_name_len);
- } else if (super_prefix) {
+ if (super_prefix) {
strbuf_add(&pathbuf, filename, tree_name_len);
strbuf_addstr(&pathbuf, super_prefix);
strbuf_addstr(&pathbuf, filename + tree_name_len);
@@ -321,6 +318,13 @@ static int grep_oid(struct grep_opt *opt, const struct object_id *oid,
strbuf_addstr(&pathbuf, filename);
}
+ if (opt->relative && opt->prefix_length) {
+ char *name = strbuf_detach(&pathbuf, NULL);
+ quote_path_relative(name + tree_name_len, opt->prefix, &pathbuf);
+ strbuf_insert(&pathbuf, 0, name, tree_name_len);
+ free(name);
+ }
+
#ifndef NO_PTHREADS
if (num_threads) {
add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, oid);
@@ -345,12 +349,14 @@ static int grep_file(struct grep_opt *opt, const char *filename)
{
struct strbuf buf = STRBUF_INIT;
+ if (super_prefix)
+ strbuf_addstr(&buf, super_prefix);
+ strbuf_addstr(&buf, filename);
+
if (opt->relative && opt->prefix_length) {
- quote_path_relative(filename, opt->prefix, &buf);
- } else {
- if (super_prefix)
- strbuf_addstr(&buf, super_prefix);
- strbuf_addstr(&buf, filename);
+ char *name = strbuf_detach(&buf, NULL);
+ quote_path_relative(name, opt->prefix, &buf);
+ free(name);
}
#ifndef NO_PTHREADS
@@ -399,13 +405,12 @@ static void run_pager(struct grep_opt *opt, const char *prefix)
}
static void compile_submodule_options(const struct grep_opt *opt,
- const struct pathspec *pathspec,
+ const char **argv,
int cached, int untracked,
int opt_exclude, int use_index,
int pattern_type_arg)
{
struct grep_pat *pattern;
- int i;
if (recurse_submodules)
argv_array_push(&submodule_options, "--recurse-submodules");
@@ -523,9 +528,8 @@ static void compile_submodule_options(const struct grep_opt *opt,
/* Add Pathspecs */
argv_array_push(&submodule_options, "--");
- for (i = 0; i < pathspec->nr; i++)
- argv_array_push(&submodule_options,
- pathspec->items[i].original);
+ for (; *argv; argv++)
+ argv_array_push(&submodule_options, *argv);
}
/*
@@ -538,7 +542,7 @@ static int grep_submodule_launch(struct grep_opt *opt,
int status, i;
const char *end_of_base;
const char *name;
- struct work_item *w = opt->output_priv;
+ struct strbuf child_output = STRBUF_INIT;
end_of_base = strchr(gs->name, ':');
if (gs->identifier && end_of_base)
@@ -549,6 +553,11 @@ static int grep_submodule_launch(struct grep_opt *opt,
prepare_submodule_repo_env(&cp.env_array);
argv_array_push(&cp.env_array, GIT_DIR_ENVIRONMENT);
+ if (opt->relative && opt->prefix_length)
+ argv_array_pushf(&cp.env_array, "%s=%s",
+ GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
+ opt->prefix);
+
/* Add super prefix */
argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
super_prefix ? super_prefix : "",
@@ -593,14 +602,16 @@ static int grep_submodule_launch(struct grep_opt *opt,
* child process. A '0' indicates a hit, a '1' indicates no hit and
* anything else is an error.
*/
- status = capture_command(&cp, &w->out, 0);
+ status = capture_command(&cp, &child_output, 0);
if (status && (status != 1)) {
/* flush the buffer */
- write_or_die(1, w->out.buf, w->out.len);
+ write_or_die(1, child_output.buf, child_output.len);
die("process for submodule '%s' failed with exit code: %d",
gs->name, status);
}
+ opt->output(opt, child_output.buf, child_output.len);
+ strbuf_release(&child_output);
/* invert the return code to make a hit equal to 1 */
return !status;
}
@@ -616,7 +627,7 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
{
if (!is_submodule_initialized(path))
return 0;
- if (!is_submodule_populated(path)) {
+ if (!is_submodule_populated_gently(path, NULL)) {
/*
* If searching history, check for the presense of the
* submodule's gitdir before skipping the submodule.
@@ -641,19 +652,14 @@ static int grep_submodule(struct grep_opt *opt, const unsigned char *sha1,
} else
#endif
{
- struct work_item w;
+ struct grep_source gs;
int hit;
- grep_source_init(&w.source, GREP_SOURCE_SUBMODULE,
+ grep_source_init(&gs, GREP_SOURCE_SUBMODULE,
filename, path, sha1);
- strbuf_init(&w.out, 0);
- opt->output_priv = &w;
- hit = grep_submodule_launch(opt, &w.source);
-
- write_or_die(1, w.out.buf, w.out.len);
+ hit = grep_submodule_launch(opt, &gs);
- grep_source_clear(&w.source);
- strbuf_release(&w.out);
+ grep_source_clear(&gs);
return hit;
}
}
@@ -979,7 +985,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_SET_INT(0, "exclude-standard", &opt_exclude,
N_("ignore files specified via '.gitignore'"), 1),
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
- N_("recursivley search in each submodule")),
+ N_("recursively search in each submodule")),
OPT_STRING(0, "parent-basename", &parent_basename,
N_("basename"),
N_("prepend parent project's basename to output")),
@@ -1236,7 +1242,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (recurse_submodules) {
gitmodules_config();
- compile_submodule_options(&opt, &pathspec, cached, untracked,
+ compile_submodule_options(&opt, argv + i, cached, untracked,
opt_exclude, use_index,
pattern_type_arg);
}
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 9028e1fdcc..bbeaf20bcc 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -102,7 +102,6 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
OPT_END()
};
int i;
- int prefix_length = -1;
const char *errstr = NULL;
argc = parse_options(argc, argv, NULL, hash_object_options,
@@ -113,9 +112,8 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
else
prefix = setup_git_directory_gently(&nongit);
- prefix_length = prefix ? strlen(prefix) : 0;
if (vpath && prefix)
- vpath = prefix_filename(prefix, prefix_length, vpath);
+ vpath = xstrdup(prefix_filename(prefix, vpath));
git_config(git_default_config, NULL);
@@ -144,11 +142,13 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
for (i = 0 ; i < argc; i++) {
const char *arg = argv[i];
+ char *to_free = NULL;
- if (0 <= prefix_length)
- arg = prefix_filename(prefix, prefix_length, arg);
+ if (prefix)
+ arg = to_free = prefix_filename(prefix, arg);
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
flags, literally);
+ free(to_free);
}
if (stdin_paths)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index f4b87c6c9f..88d205f858 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1386,7 +1386,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
unsigned char *sha1)
{
const char *report = "pack";
- char name[PATH_MAX];
+ struct strbuf pack_name = STRBUF_INIT;
+ struct strbuf index_name = STRBUF_INIT;
+ struct strbuf keep_name_buf = STRBUF_INIT;
int err;
if (!from_stdin) {
@@ -1402,14 +1404,13 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
int keep_fd, keep_msg_len = strlen(keep_msg);
if (!keep_name)
- keep_fd = odb_pack_keep(name, sizeof(name), sha1);
- else
- keep_fd = open(keep_name, O_RDWR|O_CREAT|O_EXCL, 0600);
+ keep_name = odb_pack_name(&keep_name_buf, sha1, "keep");
+ keep_fd = odb_pack_keep(keep_name);
if (keep_fd < 0) {
if (errno != EEXIST)
die_errno(_("cannot write keep file '%s'"),
- keep_name ? keep_name : name);
+ keep_name);
} else {
if (keep_msg_len > 0) {
write_or_die(keep_fd, keep_msg, keep_msg_len);
@@ -1417,28 +1418,22 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
}
if (close(keep_fd) != 0)
die_errno(_("cannot close written keep file '%s'"),
- keep_name ? keep_name : name);
+ keep_name);
report = "keep";
}
}
if (final_pack_name != curr_pack_name) {
- if (!final_pack_name) {
- snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
- get_object_directory(), sha1_to_hex(sha1));
- final_pack_name = name;
- }
+ if (!final_pack_name)
+ final_pack_name = odb_pack_name(&pack_name, sha1, "pack");
if (finalize_object_file(curr_pack_name, final_pack_name))
die(_("cannot store pack file"));
} else if (from_stdin)
chmod(final_pack_name, 0444);
if (final_index_name != curr_index_name) {
- if (!final_index_name) {
- snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
- get_object_directory(), sha1_to_hex(sha1));
- final_index_name = name;
- }
+ if (!final_index_name)
+ final_index_name = odb_pack_name(&index_name, sha1, "idx");
if (finalize_object_file(curr_index_name, final_index_name))
die(_("cannot store index file"));
} else
@@ -1464,6 +1459,10 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
input_offset += err;
}
}
+
+ strbuf_release(&index_name);
+ strbuf_release(&pack_name);
+ strbuf_release(&keep_name_buf);
}
static int git_index_pack_config(const char *k, const char *v, void *cb)
diff --git a/builtin/log.c b/builtin/log.c
index d755a59600..b3b10cc1ed 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1091,8 +1091,7 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
if (!output_directory)
return prefix;
- return xstrdup(prefix_filename(prefix, outdir_offset,
- output_directory));
+ return prefix_filename(prefix, output_directory);
}
static const char * const builtin_format_patch_usage[] = {
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 1c0f057d02..d449e46db5 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -30,7 +30,7 @@ static int line_terminator = '\n';
static int debug_mode;
static int show_eol;
static int recurse_submodules;
-static struct argv_array submodules_options = ARGV_ARRAY_INIT;
+static struct argv_array submodule_options = ARGV_ARRAY_INIT;
static const char *prefix;
static const char *super_prefix;
@@ -172,20 +172,27 @@ static void show_killed_files(struct dir_struct *dir)
/*
* Compile an argv_array with all of the options supported by --recurse_submodules
*/
-static void compile_submodule_options(const struct dir_struct *dir, int show_tag)
+static void compile_submodule_options(const char **argv,
+ const struct dir_struct *dir,
+ int show_tag)
{
if (line_terminator == '\0')
- argv_array_push(&submodules_options, "-z");
+ argv_array_push(&submodule_options, "-z");
if (show_tag)
- argv_array_push(&submodules_options, "-t");
+ argv_array_push(&submodule_options, "-t");
if (show_valid_bit)
- argv_array_push(&submodules_options, "-v");
+ argv_array_push(&submodule_options, "-v");
if (show_cached)
- argv_array_push(&submodules_options, "--cached");
+ argv_array_push(&submodule_options, "--cached");
if (show_eol)
- argv_array_push(&submodules_options, "--eol");
+ argv_array_push(&submodule_options, "--eol");
if (debug_mode)
- argv_array_push(&submodules_options, "--debug");
+ argv_array_push(&submodule_options, "--debug");
+
+ /* Add Pathspecs */
+ argv_array_push(&submodule_options, "--");
+ for (; *argv; argv++)
+ argv_array_push(&submodule_options, *argv);
}
/**
@@ -195,8 +202,11 @@ static void show_gitlink(const struct cache_entry *ce)
{
struct child_process cp = CHILD_PROCESS_INIT;
int status;
- int i;
+ if (prefix_len)
+ argv_array_pushf(&cp.env_array, "%s=%s",
+ GIT_TOPLEVEL_PREFIX_ENVIRONMENT,
+ prefix);
argv_array_pushf(&cp.args, "--super-prefix=%s%s/",
super_prefix ? super_prefix : "",
ce->name);
@@ -204,16 +214,7 @@ static void show_gitlink(const struct cache_entry *ce)
argv_array_push(&cp.args, "--recurse-submodules");
/* add supported options */
- argv_array_pushv(&cp.args, submodules_options.argv);
-
- /*
- * Pass in the original pathspec args. The submodule will be
- * responsible for prepending the 'submodule_prefix' prior to comparing
- * against the pathspec for matches.
- */
- argv_array_push(&cp.args, "--");
- for (i = 0; i < pathspec.nr; i++)
- argv_array_push(&cp.args, pathspec.items[i].original);
+ argv_array_pushv(&cp.args, submodule_options.argv);
cp.git_cmd = 1;
cp.dir = ce->name;
@@ -604,7 +605,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
setup_work_tree();
if (recurse_submodules)
- compile_submodule_options(&dir, show_tag);
+ compile_submodule_options(argv, &dir, show_tag);
if (recurse_submodules &&
(show_stage || show_deleted || show_others || show_unmerged ||
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index e3b62f2fc7..cfb667a594 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -11,13 +11,6 @@
static const char mailinfo_usage[] =
"git mailinfo [-k | -b] [-m | --message-id] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] <msg> <patch> < mail >info";
-static char *prefix_copy(const char *prefix, const char *filename)
-{
- if (!prefix || is_absolute_path(filename))
- return xstrdup(filename);
- return xstrdup(prefix_filename(prefix, strlen(prefix), filename));
-}
-
int cmd_mailinfo(int argc, const char **argv, const char *prefix)
{
const char *def_charset;
@@ -60,8 +53,8 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
mi.input = stdin;
mi.output = stdout;
- msgfile = prefix_copy(prefix, argv[1]);
- patchfile = prefix_copy(prefix, argv[2]);
+ msgfile = prefix_filename(prefix, argv[1]);
+ patchfile = prefix_filename(prefix, argv[2]);
status = !!mailinfo(&mi, msgfile, patchfile);
clear_mailinfo(&mi);
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 13e22a2f0b..47dde7c39c 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -28,7 +28,6 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
xmparam_t xmp = {{0}};
int ret = 0, i = 0, to_stdout = 0;
int quiet = 0;
- int prefixlen = 0;
struct option options[] = {
OPT_BOOL('p', "stdout", &to_stdout, N_("send results to standard output")),
OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
@@ -65,15 +64,19 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
return error_errno("failed to redirect stderr to /dev/null");
}
- if (prefix)
- prefixlen = strlen(prefix);
-
for (i = 0; i < 3; i++) {
- const char *fname = prefix_filename(prefix, prefixlen, argv[i]);
+ char *fname;
+ int ret;
+
if (!names[i])
names[i] = argv[i];
- if (read_mmfile(mmfs + i, fname))
+
+ fname = prefix_filename(prefix, argv[i]);
+ ret = read_mmfile(mmfs + i, fname);
+ free(fname);
+ if (ret)
return -1;
+
if (mmfs[i].size > MAX_XDIFF_SIZE ||
buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
return error("Cannot merge binary files: %s",
@@ -90,7 +93,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
if (ret >= 0) {
const char *filename = argv[0];
- const char *fpath = prefix_filename(prefix, prefixlen, argv[0]);
+ char *fpath = prefix_filename(prefix, argv[0]);
FILE *f = to_stdout ? stdout : fopen(fpath, "wb");
if (!f)
@@ -102,6 +105,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
else if (fclose(f))
ret = error_errno("Could not close %s", filename);
free(result.ptr);
+ free(fpath);
}
if (ret > 127)
diff --git a/builtin/merge.c b/builtin/merge.c
index 7554b8d412..95572b1810 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -44,7 +44,6 @@ struct strategy {
static const char * const builtin_merge_usage[] = {
N_("git merge [<options>] [<commit>...]"),
- N_("git merge [<options>] <msg> HEAD <commit>"),
N_("git merge --abort"),
N_("git merge --continue"),
NULL
@@ -634,9 +633,10 @@ static void write_tree_trivial(struct object_id *oid)
static int try_merge_strategy(const char *strategy, struct commit_list *common,
struct commit_list *remoteheads,
- struct commit *head, const char *head_arg)
+ struct commit *head)
{
static struct lock_file lock;
+ const char *head_arg = "HEAD";
hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
refresh_cache(REFRESH_QUIET);
@@ -853,24 +853,6 @@ static int suggest_conflicts(void)
return 1;
}
-static struct commit *is_old_style_invocation(int argc, const char **argv,
- const struct object_id *head)
-{
- struct commit *second_token = NULL;
- if (argc > 2) {
- struct object_id second_oid;
-
- if (get_oid(argv[1], &second_oid))
- return NULL;
- second_token = lookup_commit_reference_gently(second_oid.hash, 0);
- if (!second_token)
- die(_("'%s' is not a commit"), argv[1]);
- if (oidcmp(&second_token->object.oid, head))
- return NULL;
- }
- return second_token;
-}
-
static int evaluate_result(void)
{
int cnt = 0;
@@ -1120,7 +1102,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct object_id result_tree, stash, head_oid;
struct commit *head_commit;
struct strbuf buf = STRBUF_INIT;
- const char *head_arg;
int i, ret = 0, head_subsumed;
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
struct commit_list *common = NULL;
@@ -1260,34 +1241,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}
/*
- * This could be traditional "merge <msg> HEAD <commit>..." and
- * the way we can tell it is to see if the second token is HEAD,
- * but some people might have misused the interface and used a
- * commit-ish that is the same as HEAD there instead.
- * Traditional format never would have "-m" so it is an
- * additional safety measure to check for it.
+ * All the rest are the commits being merged; prepare
+ * the standard merge summary message to be appended
+ * to the given message.
*/
- if (!have_message &&
- is_old_style_invocation(argc, argv, &head_commit->object.oid)) {
- warning("old-style 'git merge <msg> HEAD <commit>' is deprecated.");
- strbuf_addstr(&merge_msg, argv[0]);
- head_arg = argv[1];
- argv += 2;
- argc -= 2;
- remoteheads = collect_parents(head_commit, &head_subsumed,
- argc, argv, NULL);
- } else {
- /* We are invoked directly as the first-class UI. */
- head_arg = "HEAD";
-
- /*
- * All the rest are the commits being merged; prepare
- * the standard merge summary message to be appended
- * to the given message.
- */
- remoteheads = collect_parents(head_commit, &head_subsumed,
- argc, argv, &merge_msg);
- }
+ remoteheads = collect_parents(head_commit, &head_subsumed,
+ argc, argv, &merge_msg);
if (!head_commit || !argc)
usage_with_options(builtin_merge_usage,
@@ -1513,7 +1472,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
ret = try_merge_strategy(use_strategies[i]->name,
common, remoteheads,
- head_commit, head_arg);
+ head_commit);
if (!option_commit && !ret) {
merge_was_ok = 1;
/*
@@ -1583,7 +1542,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
printf(_("Using the %s to prepare resolving by hand.\n"),
best_strategy);
try_merge_strategy(best_strategy, common, remoteheads,
- head_commit, head_arg);
+ head_commit);
}
if (squash)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 16517f2637..84af7c2324 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -239,7 +239,8 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
unsigned long limit, int usable_delta)
{
unsigned long size, datalen;
- unsigned char header[10], dheader[10];
+ unsigned char header[MAX_PACK_OBJECT_HEADER],
+ dheader[MAX_PACK_OBJECT_HEADER];
unsigned hdrlen;
enum object_type type;
void *buf;
@@ -286,7 +287,8 @@ static unsigned long write_no_reuse_object(struct sha1file *f, struct object_ent
* The object header is a byte of 'type' followed by zero or
* more bytes of length.
*/
- hdrlen = encode_in_pack_object_header(type, size, header);
+ hdrlen = encode_in_pack_object_header(header, sizeof(header),
+ type, size);
if (type == OBJ_OFS_DELTA) {
/*
@@ -352,13 +354,15 @@ static off_t write_reuse_object(struct sha1file *f, struct object_entry *entry,
off_t offset;
enum object_type type = entry->type;
off_t datalen;
- unsigned char header[10], dheader[10];
+ unsigned char header[MAX_PACK_OBJECT_HEADER],
+ dheader[MAX_PACK_OBJECT_HEADER];
unsigned hdrlen;
if (entry->delta)
type = (allow_ofs_delta && entry->delta->idx.offset) ?
OBJ_OFS_DELTA : OBJ_REF_DELTA;
- hdrlen = encode_in_pack_object_header(type, entry->size, header);
+ hdrlen = encode_in_pack_object_header(header, sizeof(header),
+ type, entry->size);
offset = entry->in_pack_offset;
revidx = find_pack_revindex(p, offset);
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 8ba64bc785..23e212ee8c 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -15,10 +15,13 @@
#include "builtin.h"
#include "parse-options.h"
#include "resolve-undo.h"
+#include "submodule.h"
+#include "submodule-config.h"
static int nr_trees;
static int read_empty;
static struct tree *trees[MAX_UNPACK_TREES];
+static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int list_tree(unsigned char *sha1)
{
@@ -96,6 +99,23 @@ static int debug_merge(const struct cache_entry * const *stages,
return 0;
}
+static int option_parse_recurse_submodules(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset) {
+ recurse_submodules = RECURSE_SUBMODULES_OFF;
+ return 0;
+ }
+ if (arg)
+ recurse_submodules =
+ parse_update_recurse_submodules_arg(opt->long_name,
+ arg);
+ else
+ recurse_submodules = RECURSE_SUBMODULES_ON;
+
+ return 0;
+}
+
static struct lock_file lock_file;
int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
@@ -137,6 +157,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
N_("skip applying sparse checkout filter")),
OPT_BOOL(0, "debug-unpack", &opts.debug_unpack,
N_("debug unpack-trees")),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules,
+ "checkout", "control recursive updating of submodules",
+ PARSE_OPT_OPTARG, option_parse_recurse_submodules },
OPT_END()
};
@@ -152,6 +175,12 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
+ if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) {
+ gitmodules_config();
+ git_config(submodule_config, NULL);
+ set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON);
+ }
+
prefix_set = opts.prefix ? 1 : 0;
if (1 < opts.merge + opts.reset + prefix_set)
die("Which one? -m, --reset, or --prefix?");
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 83492af05f..aca9c33d8d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1128,25 +1128,22 @@ static const char *update(struct command *cmd, struct shallow_info *si)
static void run_update_post_hook(struct command *commands)
{
struct command *cmd;
- int argc;
struct child_process proc = CHILD_PROCESS_INIT;
const char *hook;
hook = find_hook("post-update");
- for (argc = 0, cmd = commands; cmd; cmd = cmd->next) {
- if (cmd->error_string || cmd->did_not_exist)
- continue;
- argc++;
- }
- if (!argc || !hook)
+ if (!hook)
return;
- argv_array_push(&proc.args, hook);
for (cmd = commands; cmd; cmd = cmd->next) {
if (cmd->error_string || cmd->did_not_exist)
continue;
+ if (!proc.args.argc)
+ argv_array_push(&proc.args, hook);
argv_array_push(&proc.args, cmd->ref_name);
}
+ if (!proc.args.argc)
+ return;
proc.no_stdin = 1;
proc.stdout_to_stderr = 1;
@@ -1527,7 +1524,7 @@ static void queue_commands_from_cert(struct command **tail,
while (boc < eoc) {
const char *eol = memchr(boc, '\n', eoc - boc);
- tail = queue_command(tail, boc, eol ? eol - boc : eoc - eol);
+ tail = queue_command(tail, boc, eol ? eol - boc : eoc - boc);
boc = eol ? eol + 1 : eoc;
}
}
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 2549643267..9e53a1a7ca 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -228,9 +228,9 @@ static int show_file(const char *arg, int output_prefix)
if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
if (output_prefix) {
const char *prefix = startup_info->prefix;
- show(prefix_filename(prefix,
- prefix ? strlen(prefix) : 0,
- arg));
+ char *fname = prefix_filename(prefix, arg);
+ show(fname);
+ free(fname);
} else
show(arg);
return 1;
@@ -536,6 +536,34 @@ N_("git rev-parse --parseopt [<options>] -- [<args>...]\n"
"\n"
"Run \"git rev-parse --parseopt -h\" for more information on the first usage.");
+/*
+ * Parse "opt" or "opt=<value>", setting value respectively to either
+ * NULL or the string after "=".
+ */
+static int opt_with_value(const char *arg, const char *opt, const char **value)
+{
+ if (skip_prefix(arg, opt, &arg)) {
+ if (!*arg) {
+ *value = NULL;
+ return 1;
+ }
+ if (*arg++ == '=') {
+ *value = arg;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void handle_ref_opt(const char *pattern, const char *prefix)
+{
+ if (pattern)
+ for_each_glob_ref_in(show_reference, pattern, prefix, NULL);
+ else
+ for_each_ref_in(prefix, show_reference, NULL);
+ clear_ref_exclusion(&ref_excludes);
+}
+
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
@@ -675,14 +703,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
flags |= GET_SHA1_QUIETLY;
continue;
}
- if (!strcmp(arg, "--short") ||
- starts_with(arg, "--short=")) {
+ if (opt_with_value(arg, "--short", &arg)) {
filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1;
abbrev = DEFAULT_ABBREV;
- if (!arg[7])
+ if (!arg)
continue;
- abbrev = strtoul(arg + 8, NULL, 10);
+ abbrev = strtoul(arg, NULL, 10);
if (abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
else if (40 <= abbrev)
@@ -705,17 +732,17 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
symbolic = SHOW_SYMBOLIC_FULL;
continue;
}
- if (starts_with(arg, "--abbrev-ref") &&
- (!arg[12] || arg[12] == '=')) {
+ if (opt_with_value(arg, "--abbrev-ref", &arg)) {
abbrev_ref = 1;
abbrev_ref_strict = warn_ambiguous_refs;
- if (arg[12] == '=') {
- if (!strcmp(arg + 13, "strict"))
+ if (arg) {
+ if (!strcmp(arg, "strict"))
abbrev_ref_strict = 1;
- else if (!strcmp(arg + 13, "loose"))
+ else if (!strcmp(arg, "loose"))
abbrev_ref_strict = 0;
else
- die("unknown mode for %s", arg);
+ die("unknown mode for --abbrev-ref: %s",
+ arg);
}
continue;
}
@@ -723,8 +750,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
for_each_ref(show_reference, NULL);
continue;
}
- if (starts_with(arg, "--disambiguate=")) {
- for_each_abbrev(arg + 15, show_abbrev, NULL);
+ if (skip_prefix(arg, "--disambiguate=", &arg)) {
+ for_each_abbrev(arg, show_abbrev, NULL);
continue;
}
if (!strcmp(arg, "--bisect")) {
@@ -732,46 +759,24 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
for_each_ref_in("refs/bisect/good", anti_reference, NULL);
continue;
}
- if (starts_with(arg, "--branches=")) {
- for_each_glob_ref_in(show_reference, arg + 11,
- "refs/heads/", NULL);
- clear_ref_exclusion(&ref_excludes);
- continue;
- }
- if (!strcmp(arg, "--branches")) {
- for_each_branch_ref(show_reference, NULL);
- clear_ref_exclusion(&ref_excludes);
- continue;
- }
- if (starts_with(arg, "--tags=")) {
- for_each_glob_ref_in(show_reference, arg + 7,
- "refs/tags/", NULL);
- clear_ref_exclusion(&ref_excludes);
- continue;
- }
- if (!strcmp(arg, "--tags")) {
- for_each_tag_ref(show_reference, NULL);
- clear_ref_exclusion(&ref_excludes);
+ if (opt_with_value(arg, "--branches", &arg)) {
+ handle_ref_opt(arg, "refs/heads/");
continue;
}
- if (starts_with(arg, "--glob=")) {
- for_each_glob_ref(show_reference, arg + 7, NULL);
- clear_ref_exclusion(&ref_excludes);
+ if (opt_with_value(arg, "--tags", &arg)) {
+ handle_ref_opt(arg, "refs/tags/");
continue;
}
- if (starts_with(arg, "--remotes=")) {
- for_each_glob_ref_in(show_reference, arg + 10,
- "refs/remotes/", NULL);
- clear_ref_exclusion(&ref_excludes);
+ if (skip_prefix(arg, "--glob=", &arg)) {
+ handle_ref_opt(arg, NULL);
continue;
}
- if (!strcmp(arg, "--remotes")) {
- for_each_remote_ref(show_reference, NULL);
- clear_ref_exclusion(&ref_excludes);
+ if (opt_with_value(arg, "--remotes", &arg)) {
+ handle_ref_opt(arg, "refs/remotes/");
continue;
}
- if (starts_with(arg, "--exclude=")) {
- add_ref_exclusion(&ref_excludes, arg + 10);
+ if (skip_prefix(arg, "--exclude=", &arg)) {
+ add_ref_exclusion(&ref_excludes, arg);
continue;
}
if (!strcmp(arg, "--show-toplevel")) {
@@ -872,20 +877,20 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
continue;
}
- if (starts_with(arg, "--since=")) {
- show_datestring("--max-age=", arg+8);
+ if (skip_prefix(arg, "--since=", &arg)) {
+ show_datestring("--max-age=", arg);
continue;
}
- if (starts_with(arg, "--after=")) {
- show_datestring("--max-age=", arg+8);
+ if (skip_prefix(arg, "--after=", &arg)) {
+ show_datestring("--max-age=", arg);
continue;
}
- if (starts_with(arg, "--before=")) {
- show_datestring("--min-age=", arg+9);
+ if (skip_prefix(arg, "--before=", &arg)) {
+ show_datestring("--min-age=", arg);
continue;
}
- if (starts_with(arg, "--until=")) {
- show_datestring("--min-age=", arg+8);
+ if (skip_prefix(arg, "--until=", &arg)) {
+ show_datestring("--min-age=", arg);
continue;
}
if (show_flag(arg) && verify)
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 1ff5a67538..832fd7ed0a 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -144,6 +144,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
unsigned force_update = 0;
unsigned quiet = 0;
int push_cert = 0;
+ struct string_list push_options = STRING_LIST_INIT_NODUP;
unsigned use_thin_pack = 0;
unsigned atomic = 0;
unsigned stateless_rpc = 0;
@@ -165,6 +166,9 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
{ OPTION_CALLBACK,
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
PARSE_OPT_OPTARG, option_parse_push_signed },
+ OPT_STRING_LIST(0, "push-option", &push_options,
+ N_("server-specific"),
+ N_("option to transmit")),
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
OPT_BOOL(0, "thin", &use_thin_pack, N_("use thin pack")),
OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")),
@@ -199,6 +203,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
args.use_thin_pack = use_thin_pack;
args.atomic = atomic;
args.stateless_rpc = stateless_rpc;
+ args.push_options = push_options.nr ? &push_options : NULL;
if (from_stdin) {
struct argv_array all_refspecs = ARGV_ARRAY_INIT;
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index f78bb4818d..7cff1839fc 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -149,7 +149,6 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
ctx.fmt = CMIT_FMT_USERFORMAT;
ctx.abbrev = log->abbrev;
ctx.print_email_subject = 1;
- ctx.after_subject = "";
ctx.date_mode.type = DATE_NORMAL;
ctx.output_encoding = get_log_output_encoding();
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 15a5430c00..85aafe46a4 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -270,6 +270,29 @@ static int module_list_compute(int argc, const char **argv,
return result;
}
+static void module_list_active(struct module_list *list)
+{
+ int i;
+ struct module_list active_modules = MODULE_LIST_INIT;
+
+ gitmodules_config();
+
+ for (i = 0; i < list->nr; i++) {
+ const struct cache_entry *ce = list->entries[i];
+
+ if (!is_submodule_initialized(ce->name))
+ continue;
+
+ ALLOC_GROW(active_modules.entries,
+ active_modules.nr + 1,
+ active_modules.alloc);
+ active_modules.entries[active_modules.nr++] = ce;
+ }
+
+ free(list->entries);
+ *list = active_modules;
+}
+
static int module_list(int argc, const char **argv, const char *prefix)
{
int i;
@@ -334,6 +357,18 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
displaypath);
/*
+ * NEEDSWORK: In a multi-working-tree world, this needs to be
+ * set in the per-worktree config.
+ *
+ * Set active flag for the submodule being initialized
+ */
+ if (!is_submodule_initialized(path)) {
+ strbuf_reset(&sb);
+ strbuf_addf(&sb, "submodule.%s.active", sub->name);
+ git_config_set_gently(sb.buf, "true");
+ }
+
+ /*
* Copy url setting when it is not set yet.
* To look up the url in .git/config, we must not fall back to
* .gitmodules, so look it up directly.
@@ -420,6 +455,13 @@ static int module_init(int argc, const char **argv, const char *prefix)
if (module_list_compute(argc, argv, prefix, &pathspec, &list) < 0)
return 1;
+ /*
+ * If there are no path args and submodule.active is set then,
+ * by default, only initialize 'active' modules.
+ */
+ if (!argc && git_config_get_value_multi("submodule.active"))
+ module_list_active(&list);
+
for (i = 0; i < list.nr; i++)
init_submodule(list.entries[i]->name, prefix, quiet);
@@ -577,9 +619,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
const char *name = NULL, *url = NULL, *depth = NULL;
int quiet = 0;
int progress = 0;
- FILE *submodule_dot_git;
char *p, *path = NULL, *sm_gitdir;
- struct strbuf rel_path = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
struct string_list reference = STRING_LIST_INIT_NODUP;
char *sm_alternate = NULL, *error_strategy = NULL;
@@ -651,27 +691,12 @@ static int module_clone(int argc, const char **argv, const char *prefix)
strbuf_reset(&sb);
}
- /* Write a .git file in the submodule to redirect to the superproject. */
- strbuf_addf(&sb, "%s/.git", path);
- if (safe_create_leading_directories_const(sb.buf) < 0)
- die(_("could not create leading directories of '%s'"), sb.buf);
- submodule_dot_git = fopen(sb.buf, "w");
- if (!submodule_dot_git)
- die_errno(_("cannot open file '%s'"), sb.buf);
-
- fprintf_or_die(submodule_dot_git, "gitdir: %s\n",
- relative_path(sm_gitdir, path, &rel_path));
- if (fclose(submodule_dot_git))
- die(_("could not close file %s"), sb.buf);
- strbuf_reset(&sb);
- strbuf_reset(&rel_path);
+ /* Connect module worktree and git dir */
+ connect_work_tree_and_git_dir(path, sm_gitdir);
- /* Redirect the worktree of the submodule in the superproject's config */
p = git_pathdup_submodule(path, "config");
if (!p)
die(_("could not get submodule directory for '%s'"), path);
- git_config_set_in_file(p, "core.worktree",
- relative_path(path, sm_gitdir, &rel_path));
/* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */
git_config_get_string("submodule.alternateLocation", &sm_alternate);
@@ -687,7 +712,6 @@ static int module_clone(int argc, const char **argv, const char *prefix)
free(error_strategy);
strbuf_release(&sb);
- strbuf_release(&rel_path);
free(sm_gitdir);
free(path);
free(p);
@@ -759,7 +783,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
struct strbuf displaypath_sb = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
const char *displaypath = NULL;
- char *url = NULL;
int needs_cloning = 0;
if (ce_stage(ce)) {
@@ -793,15 +816,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
goto cleanup;
}
- /*
- * Looking up the url in .git/config.
- * We must not fall back to .gitmodules as we only want
- * to process configured submodules.
- */
- strbuf_reset(&sb);
- strbuf_addf(&sb, "submodule.%s.url", sub->name);
- git_config_get_string(sb.buf, &url);
- if (!url) {
+ /* Check if the submodule has been initialized. */
+ if (!is_submodule_initialized(ce->name)) {
next_submodule_warn_missing(suc, out, displaypath);
goto cleanup;
}
@@ -835,7 +851,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
argv_array_push(&child->args, "--depth=1");
argv_array_pushl(&child->args, "--path", sub->path, NULL);
argv_array_pushl(&child->args, "--name", sub->name, NULL);
- argv_array_pushl(&child->args, "--url", url, NULL);
+ argv_array_pushl(&child->args, "--url", sub->url, NULL);
if (suc->references.nr) {
struct string_list_item *item;
for_each_string_list_item(item, &suc->references)
@@ -845,7 +861,6 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
argv_array_push(&child->args, suc->depth);
cleanup:
- free(url);
strbuf_reset(&displaypath_sb);
strbuf_reset(&sb);
@@ -1127,6 +1142,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
return 0;
}
+static int is_active(int argc, const char **argv, const char *prefix)
+{
+ if (argc != 2)
+ die("submodule--helper is-active takes exactly 1 arguments");
+
+ gitmodules_config();
+
+ return !is_submodule_initialized(argv[1]);
+}
+
#define SUPPORT_SUPER_PREFIX (1<<0)
struct cmd_struct {
@@ -1146,6 +1171,7 @@ static struct cmd_struct commands[] = {
{"init", module_init, SUPPORT_SUPER_PREFIX},
{"remote-branch", resolve_remote_submodule_branch, 0},
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
+ {"is-active", is_active, 0},
};
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
diff --git a/builtin/tag.c b/builtin/tag.c
index ad29be6923..dbc6f5b74b 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -22,7 +22,7 @@
static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"),
N_("git tag -d <tagname>..."),
- N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]"
+ N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]"
"\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
N_("git tag -v [--format=<format>] <tagname>..."),
NULL
@@ -424,14 +424,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
OPT_CONTAINS(&filter.with_commit, N_("print only tags that contain the commit")),
+ OPT_NO_CONTAINS(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_WITH(&filter.with_commit, N_("print only tags that contain the commit")),
+ OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_MERGED(&filter, N_("print only tags that are merged")),
OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), &parse_opt_ref_sorting),
{
OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
- N_("print only tags of the object"), 0, parse_opt_object_name
+ N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
+ parse_opt_object_name, (intptr_t) "HEAD"
},
OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
@@ -454,8 +457,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
}
create_tag_object = (opt.sign || annotate || msg.given || msgfile);
- if (argc == 0 && !cmdmode)
- cmdmode = 'l';
+ if (!cmdmode) {
+ if (argc == 0)
+ cmdmode = 'l';
+ else if (filter.with_commit || filter.no_commit ||
+ filter.points_at.nr || filter.merge_commit ||
+ filter.lines != -1)
+ cmdmode = 'l';
+ }
if ((create_tag_object || force) && (cmdmode != 0))
usage_with_options(git_tag_usage, options);
@@ -485,13 +494,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
return ret;
}
if (filter.lines != -1)
- die(_("-n option is only allowed with -l."));
+ die(_("-n option is only allowed in list mode"));
if (filter.with_commit)
- die(_("--contains option is only allowed with -l."));
+ die(_("--contains option is only allowed in list mode"));
+ if (filter.no_commit)
+ die(_("--no-contains option is only allowed in list mode"));
if (filter.points_at.nr)
- die(_("--points-at option is only allowed with -l."));
+ die(_("--points-at option is only allowed in list mode"));
if (filter.merge_commit)
- die(_("--merged and --no-merged option are only allowed with -l"));
+ die(_("--merged and --no-merged options are only allowed in list mode"));
if (cmdmode == 'd')
return for_each_tag_name(argv, delete_tag, NULL);
if (cmdmode == 'v') {
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 831fe058a5..9993ded41a 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -318,7 +318,8 @@ static int add(int ac, const char **av, const char *prefix)
{
struct add_opts opts;
const char *new_branch_force = NULL;
- const char *path, *branch;
+ char *path;
+ const char *branch;
struct option options[] = {
OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")),
OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
@@ -338,7 +339,7 @@ static int add(int ac, const char **av, const char *prefix)
if (ac < 1 || ac > 2)
usage_with_options(worktree_usage, options);
- path = prefix_filename(prefix, strlen(prefix), av[0]);
+ path = prefix_filename(prefix, av[0]);
branch = ac < 2 ? "HEAD" : av[1];
if (!strcmp(branch, "-"))