summaryrefslogtreecommitdiff
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/am.c18
-rw-r--r--builtin/blame.c3
-rw-r--r--builtin/branch.c35
-rw-r--r--builtin/clean.c29
-rw-r--r--builtin/commit.c36
-rw-r--r--builtin/describe.c16
-rw-r--r--builtin/diff.c7
-rw-r--r--builtin/difftool.c9
-rw-r--r--builtin/fast-export.c14
-rw-r--r--builtin/fetch.c6
-rw-r--r--builtin/grep.c6
-rw-r--r--builtin/help.c56
-rw-r--r--builtin/index-pack.c8
-rw-r--r--builtin/init-db.c2
-rw-r--r--builtin/log.c23
-rw-r--r--builtin/ls-files.c6
-rw-r--r--builtin/merge.c39
-rw-r--r--builtin/name-rev.c23
-rw-r--r--builtin/notes.c12
-rw-r--r--builtin/pack-objects.c24
-rw-r--r--builtin/pull.c4
-rw-r--r--builtin/rev-parse.c8
-rw-r--r--builtin/show-branch.c44
-rw-r--r--builtin/show-index.c86
-rw-r--r--builtin/submodule--helper.c144
-rw-r--r--builtin/update-ref.c25
26 files changed, 485 insertions, 198 deletions
diff --git a/builtin/am.c b/builtin/am.c
index aa989e7390..6273ea5195 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1827,15 +1827,11 @@ static void am_run(struct am_state *state, int resume)
}
if (apply_status) {
- int advice_amworkdir = 1;
-
printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
linelen(state->msg), state->msg);
- git_config_get_bool("advice.amworkdir", &advice_amworkdir);
-
if (advice_amworkdir)
- printf_ln(_("Use 'git am --show-current-patch' to see the failed patch"));
+ advise(_("Use 'git am --show-current-patch' to see the failed patch"));
die_user_resolve(state);
}
@@ -2231,12 +2227,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),
OPT_BOOL('m', "message-id", &state.message_id,
N_("pass -m flag to git-mailinfo")),
- { OPTION_SET_INT, 0, "keep-cr", &keep_cr, NULL,
- N_("pass --keep-cr flag to git-mailsplit for mbox format"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
- { OPTION_SET_INT, 0, "no-keep-cr", &keep_cr, NULL,
- N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
+ OPT_SET_INT_F(0, "keep-cr", &keep_cr,
+ N_("pass --keep-cr flag to git-mailsplit for mbox format"),
+ 1, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "no-keep-cr", &keep_cr,
+ N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
+ 0, PARSE_OPT_NONEG),
OPT_BOOL('c', "scissors", &state.scissors,
N_("strip everything before a scissors line")),
OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
diff --git a/builtin/blame.c b/builtin/blame.c
index 4202584f97..5a0388aaef 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -411,6 +411,7 @@ static void parse_color_fields(const char *s)
die (_("must end with a color"));
colorfield[colorfield_nr].hop = TIME_MAX;
+ string_list_clear(&l, 0);
}
static void setup_default_color_by_age(void)
@@ -542,7 +543,7 @@ static void output(struct blame_scoreboard *sb, int option)
struct commit *commit = ent->suspect->commit;
if (commit->object.flags & MORE_THAN_ONE_PATH)
continue;
- for (suspect = commit->util; suspect; suspect = suspect->next) {
+ for (suspect = get_blame_suspects(commit); suspect; suspect = suspect->next) {
if (suspect->guilty && count++) {
commit->object.flags |= MORE_THAN_ONE_PATH;
break;
diff --git a/builtin/branch.c b/builtin/branch.c
index 5bb5123e72..1876ca9e79 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -22,6 +22,7 @@
#include "wt-status.h"
#include "ref-filter.h"
#include "worktree.h"
+#include "help.h"
static const char * const builtin_branch_usage[] = {
N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
@@ -55,25 +56,19 @@ enum color_branch {
BRANCH_COLOR_UPSTREAM = 5
};
+static const char *color_branch_slots[] = {
+ [BRANCH_COLOR_RESET] = "reset",
+ [BRANCH_COLOR_PLAIN] = "plain",
+ [BRANCH_COLOR_REMOTE] = "remote",
+ [BRANCH_COLOR_LOCAL] = "local",
+ [BRANCH_COLOR_CURRENT] = "current",
+ [BRANCH_COLOR_UPSTREAM] = "upstream",
+};
+
static struct string_list output = STRING_LIST_INIT_DUP;
static unsigned int colopts;
-static int parse_branch_color_slot(const char *slot)
-{
- if (!strcasecmp(slot, "plain"))
- return BRANCH_COLOR_PLAIN;
- if (!strcasecmp(slot, "reset"))
- return BRANCH_COLOR_RESET;
- if (!strcasecmp(slot, "remote"))
- return BRANCH_COLOR_REMOTE;
- if (!strcasecmp(slot, "local"))
- return BRANCH_COLOR_LOCAL;
- if (!strcasecmp(slot, "current"))
- return BRANCH_COLOR_CURRENT;
- if (!strcasecmp(slot, "upstream"))
- return BRANCH_COLOR_UPSTREAM;
- return -1;
-}
+define_list_config_array(color_branch_slots);
static int git_branch_config(const char *var, const char *value, void *cb)
{
@@ -86,7 +81,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
return 0;
}
if (skip_prefix(var, "color.branch.", &slot_name)) {
- int slot = parse_branch_color_slot(slot_name);
+ int slot = LOOKUP_CONFIG(color_branch_slots, slot_name);
if (slot < 0)
return 0;
if (!value)
@@ -592,8 +587,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
OPT__QUIET(&quiet, N_("suppress informational messages")),
OPT_SET_INT('t', "track", &track, N_("set up tracking mode (see git-pull(1))"),
BRANCH_TRACK_EXPLICIT),
- { OPTION_SET_INT, 0, "set-upstream", &track, NULL, N_("do not use"),
- PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, BRANCH_TRACK_OVERRIDE },
+ OPT_SET_INT_F(0, "set-upstream", &track, N_("do not use"),
+ BRANCH_TRACK_OVERRIDE, PARSE_OPT_HIDDEN),
OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")),
OPT_BOOL(0, "unset-upstream", &unset_upstream, N_("Unset the upstream info")),
OPT__COLOR(&branch_use_color, N_("use colored output")),
@@ -701,7 +696,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
* If no sorting parameter is given then we default to sorting
* by 'refname'. This would give us an alphabetically sorted
* array with the 'HEAD' ref at the beginning followed by
- * local branches 'refs/heads/...' and finally remote-tacking
+ * local branches 'refs/heads/...' and finally remote-tracking
* branches 'refs/remotes/...'.
*/
if (!sorting)
diff --git a/builtin/clean.c b/builtin/clean.c
index fad533a0a7..ab402c204c 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -16,6 +16,7 @@
#include "column.h"
#include "color.h"
#include "pathspec.h"
+#include "help.h"
static int force = -1; /* unset */
static int interactive;
@@ -42,6 +43,15 @@ enum color_clean {
CLEAN_COLOR_ERROR = 5
};
+static const char *color_interactive_slots[] = {
+ [CLEAN_COLOR_ERROR] = "error",
+ [CLEAN_COLOR_HEADER] = "header",
+ [CLEAN_COLOR_HELP] = "help",
+ [CLEAN_COLOR_PLAIN] = "plain",
+ [CLEAN_COLOR_PROMPT] = "prompt",
+ [CLEAN_COLOR_RESET] = "reset",
+};
+
static int clean_use_color = -1;
static char clean_colors[][COLOR_MAXLEN] = {
[CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
@@ -82,22 +92,7 @@ struct menu_stuff {
void *stuff;
};
-static int parse_clean_color_slot(const char *var)
-{
- if (!strcasecmp(var, "reset"))
- return CLEAN_COLOR_RESET;
- if (!strcasecmp(var, "plain"))
- return CLEAN_COLOR_PLAIN;
- if (!strcasecmp(var, "prompt"))
- return CLEAN_COLOR_PROMPT;
- if (!strcasecmp(var, "header"))
- return CLEAN_COLOR_HEADER;
- if (!strcasecmp(var, "help"))
- return CLEAN_COLOR_HELP;
- if (!strcasecmp(var, "error"))
- return CLEAN_COLOR_ERROR;
- return -1;
-}
+define_list_config_array(color_interactive_slots);
static int git_clean_config(const char *var, const char *value, void *cb)
{
@@ -113,7 +108,7 @@ static int git_clean_config(const char *var, const char *value, void *cb)
return 0;
}
if (skip_prefix(var, "color.interactive.", &slot_name)) {
- int slot = parse_clean_color_slot(slot_name);
+ int slot = LOOKUP_CONFIG(color_interactive_slots, slot_name);
if (slot < 0)
return 0;
if (!value)
diff --git a/builtin/commit.c b/builtin/commit.c
index a842fea666..9bcbb0c25c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -32,6 +32,7 @@
#include "column.h"
#include "sequencer.h"
#include "mailmap.h"
+#include "help.h"
static const char * const builtin_commit_usage[] = {
N_("git commit [<options>] [--] <pathspec>..."),
@@ -66,6 +67,18 @@ N_("If you wish to skip this commit, use:\n"
"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
"the remaining commits.\n");
+static const char *color_status_slots[] = {
+ [WT_STATUS_HEADER] = "header",
+ [WT_STATUS_UPDATED] = "updated",
+ [WT_STATUS_CHANGED] = "changed",
+ [WT_STATUS_UNTRACKED] = "untracked",
+ [WT_STATUS_NOBRANCH] = "noBranch",
+ [WT_STATUS_UNMERGED] = "unmerged",
+ [WT_STATUS_LOCAL_BRANCH] = "localBranch",
+ [WT_STATUS_REMOTE_BRANCH] = "remoteBranch",
+ [WT_STATUS_ONBRANCH] = "branch",
+};
+
static const char *use_message_buffer;
static struct lock_file index_lock; /* real index */
static struct lock_file false_lock; /* used only for partial commits */
@@ -1183,27 +1196,14 @@ static int dry_run_commit(int argc, const char **argv, const char *prefix,
return commitable ? 0 : 1;
}
+define_list_config_array_extra(color_status_slots, {"added"});
+
static int parse_status_slot(const char *slot)
{
- if (!strcasecmp(slot, "header"))
- return WT_STATUS_HEADER;
- if (!strcasecmp(slot, "branch"))
- return WT_STATUS_ONBRANCH;
- if (!strcasecmp(slot, "updated") || !strcasecmp(slot, "added"))
+ if (!strcasecmp(slot, "added"))
return WT_STATUS_UPDATED;
- if (!strcasecmp(slot, "changed"))
- return WT_STATUS_CHANGED;
- if (!strcasecmp(slot, "untracked"))
- return WT_STATUS_UNTRACKED;
- if (!strcasecmp(slot, "nobranch"))
- return WT_STATUS_NOBRANCH;
- if (!strcasecmp(slot, "unmerged"))
- return WT_STATUS_UNMERGED;
- if (!strcasecmp(slot, "localBranch"))
- return WT_STATUS_LOCAL_BRANCH;
- if (!strcasecmp(slot, "remoteBranch"))
- return WT_STATUS_REMOTE_BRANCH;
- return -1;
+
+ return LOOKUP_CONFIG(color_status_slots, slot);
}
static int git_status_config(const char *k, const char *v, void *cb)
diff --git a/builtin/describe.c b/builtin/describe.c
index cf1ae77d7c..bec2513b66 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -15,9 +15,12 @@
#include "run-command.h"
#include "revision.h"
#include "list-objects.h"
+#include "commit-slab.h"
#define MAX_TAGS (FLAG_BITS - 1)
+define_commit_slab(commit_names, struct commit_name *);
+
static const char * const describe_usage[] = {
N_("git describe [<options>] [<commit-ish>...]"),
N_("git describe [<options>] --dirty"),
@@ -37,6 +40,7 @@ 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 *suffix, *dirty, *broken;
+static struct commit_names commit_names;
/* diff-index command arguments to check if working tree is dirty. */
static const char *diff_index_args[] = {
@@ -321,11 +325,14 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
if (!have_util) {
struct hashmap_iter iter;
struct commit *c;
- struct commit_name *n = hashmap_iter_first(&names, &iter);
+ struct commit_name *n;
+
+ init_commit_names(&commit_names);
+ n = hashmap_iter_first(&names, &iter);
for (; n; n = hashmap_iter_next(&iter)) {
c = lookup_commit_reference_gently(&n->peeled, 1);
if (c)
- c->util = n;
+ *commit_names_at(&commit_names, c) = n;
}
have_util = 1;
}
@@ -336,8 +343,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
while (list) {
struct commit *c = pop_commit(&list);
struct commit_list *parents = c->parents;
+ struct commit_name **slot;
+
seen_commits++;
- n = c->util;
+ slot = commit_names_peek(&commit_names, c);
+ n = slot ? *slot : NULL;
if (n) {
if (!tags && !all && n->prio < 2) {
unannotated_cnt++;
diff --git a/builtin/diff.c b/builtin/diff.c
index bfefff3a84..b709b6e984 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -352,6 +352,13 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
rev.diffopt.flags.allow_external = 1;
rev.diffopt.flags.allow_textconv = 1;
+ /*
+ * Default to intent-to-add entries invisible in the
+ * index. This makes them show up as new files in diff-files
+ * and not at all in diff-cached.
+ */
+ rev.diffopt.ita_invisible_in_index = 1;
+
if (nongit)
die(_("Not a git repository"));
argc = setup_revisions(argc, argv, &rev, NULL);
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 162806f238..bc97d4aef2 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -695,12 +695,11 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
N_("use `diff.guitool` instead of `diff.tool`")),
OPT_BOOL('d', "dir-diff", &dir_diff,
N_("perform a full-directory diff")),
- { OPTION_SET_INT, 'y', "no-prompt", &prompt, NULL,
+ OPT_SET_INT_F('y', "no-prompt", &prompt,
N_("do not prompt before launching a diff tool"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
- { OPTION_SET_INT, 0, "prompt", &prompt, NULL, NULL,
- PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_HIDDEN,
- NULL, 1 },
+ 0, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "prompt", &prompt, NULL,
+ 1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN),
OPT_BOOL(0, "symlinks", &symlinks,
N_("use symlinks in dir-diff mode")),
OPT_STRING('t', "tool", &difftool_cmd, N_("<tool>"),
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 6c9768742f..73d12c1020 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -22,6 +22,7 @@
#include "quote.h"
#include "remote.h"
#include "blob.h"
+#include "commit-slab.h"
static const char *fast_export_usage[] = {
N_("git fast-export [rev-list-opts]"),
@@ -38,6 +39,7 @@ static int full_tree;
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
static struct refspec refspecs = REFSPEC_INIT_FETCH;
static int anonymize;
+static struct revision_sources revision_sources;
static int parse_opt_signed_tag_mode(const struct option *opt,
const char *arg, int unset)
@@ -589,7 +591,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
export_blob(&diff_queued_diff.queue[i]->two->oid);
- refname = commit->util;
+ refname = *revision_sources_at(&revision_sources, commit);
if (anonymize) {
refname = anonymize_refname(refname);
anonymize_ident_line(&committer, &committer_end);
@@ -861,10 +863,11 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
* This ref will not be updated through a commit, lets make
* sure it gets properly updated eventually.
*/
- if (commit->util || commit->object.flags & SHOWN)
+ if (*revision_sources_at(&revision_sources, commit) ||
+ commit->object.flags & SHOWN)
string_list_append(&extra_refs, full_name)->util = commit;
- if (!commit->util)
- commit->util = full_name;
+ if (!*revision_sources_at(&revision_sources, commit))
+ *revision_sources_at(&revision_sources, commit) = full_name;
}
}
@@ -1028,8 +1031,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
init_revisions(&revs, prefix);
+ init_revision_sources(&revision_sources);
revs.topo_order = 1;
- revs.show_source = 1;
+ revs.sources = &revision_sources;
revs.rewrite_parents = 1;
argc = parse_options(argc, argv, prefix, options, fast_export_usage,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index c0d8ad1fe2..ea5b9669ad 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -155,9 +155,9 @@ static struct option builtin_fetch_options[] = {
N_("deepen history of shallow clone, excluding rev")),
OPT_INTEGER(0, "deepen", &deepen_relative,
N_("deepen history of shallow clone")),
- { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
- N_("convert to a complete repository"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },
+ OPT_SET_INT_F(0, "unshallow", &unshallow,
+ N_("convert to a complete repository"),
+ 1, PARSE_OPT_NONEG),
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
{ OPTION_CALLBACK, 0, "recurse-submodules-default",
diff --git a/builtin/grep.c b/builtin/grep.c
index 69f0743619..ee753a403e 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -886,9 +886,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
N_("indicate hit with exit status without output")),
OPT_BOOL(0, "all-match", &opt.all_match,
N_("show only matches from files that match all patterns")),
- { OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
- N_("show parse tree for grep expression"),
- PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
+ OPT_SET_INT_F(0, "debug", &opt.debug,
+ N_("show parse tree for grep expression"),
+ 1, PARSE_OPT_HIDDEN),
OPT_GROUP(""),
{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
N_("pager"), N_("show matching files in the pager"),
diff --git a/builtin/help.c b/builtin/help.c
index 2d51071429..8d4f6dd301 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -9,6 +9,7 @@
#include "run-command.h"
#include "column.h"
#include "help.h"
+#include "alias.h"
#ifndef DEFAULT_HELP_FORMAT
#define DEFAULT_HELP_FORMAT "man"
@@ -36,6 +37,8 @@ static const char *html_path;
static int show_all = 0;
static int show_guides = 0;
+static int show_config;
+static int verbose;
static unsigned int colopts;
static enum help_format help_format = HELP_FORMAT_NONE;
static int exclude_guides;
@@ -43,11 +46,14 @@ static struct option builtin_help_options[] = {
OPT_BOOL('a', "all", &show_all, N_("print all available commands")),
OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")),
OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")),
+ OPT_BOOL('c', "config", &show_config, N_("print all configuration variable names")),
+ OPT_SET_INT_F(0, "config-for-completion", &show_config, "", 2, PARSE_OPT_HIDDEN),
OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN),
OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"),
HELP_FORMAT_WEB),
OPT_SET_INT('i', "info", &help_format, N_("show info page"),
HELP_FORMAT_INFO),
+ OPT__VERBOSE(&verbose, N_("print command description")),
OPT_END(),
};
@@ -400,38 +406,6 @@ static void show_html_page(const char *git_cmd)
open_html(page_path.buf);
}
-static struct {
- const char *name;
- const char *help;
-} common_guides[] = {
- { "attributes", N_("Defining attributes per path") },
- { "everyday", N_("Everyday Git With 20 Commands Or So") },
- { "glossary", N_("A Git glossary") },
- { "ignore", N_("Specifies intentionally untracked files to ignore") },
- { "modules", N_("Defining submodule properties") },
- { "revisions", N_("Specifying revisions and ranges for Git") },
- { "tutorial", N_("A tutorial introduction to Git (for version 1.5.1 or newer)") },
- { "workflows", N_("An overview of recommended workflows with Git") },
-};
-
-static void list_common_guides_help(void)
-{
- int i, longest = 0;
-
- for (i = 0; i < ARRAY_SIZE(common_guides); i++) {
- if (longest < strlen(common_guides[i].name))
- longest = strlen(common_guides[i].name);
- }
-
- puts(_("The common Git guides are:\n"));
- for (i = 0; i < ARRAY_SIZE(common_guides); i++) {
- printf(" %s ", common_guides[i].name);
- mput_char(' ', longest - strlen(common_guides[i].name));
- puts(_(common_guides[i].help));
- }
- putchar('\n');
-}
-
static const char *check_git_cmd(const char* cmd)
{
char *alias;
@@ -463,11 +437,29 @@ int cmd_help(int argc, const char **argv, const char *prefix)
if (show_all) {
git_config(git_help_config, NULL);
+ if (verbose) {
+ setup_pager();
+ list_all_cmds_help();
+ return 0;
+ }
printf(_("usage: %s%s"), _(git_usage_string), "\n\n");
load_command_list("git-", &main_cmds, &other_cmds);
list_commands(colopts, &main_cmds, &other_cmds);
}
+ if (show_config) {
+ int for_human = show_config == 1;
+
+ if (!for_human) {
+ list_config_help(for_human);
+ return 0;
+ }
+ setup_pager();
+ list_config_help(for_human);
+ printf("\n%s\n", _("'git help config' for more information"));
+ return 0;
+ }
+
if (show_guides)
list_common_guides_help();
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 4ab31ed388..74fe2973e1 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1482,8 +1482,12 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
} else
chmod(final_index_name, 0444);
- if (do_fsck_object)
- add_packed_git(final_index_name, strlen(final_index_name), 0);
+ if (do_fsck_object) {
+ struct packed_git *p;
+ p = add_packed_git(final_index_name, strlen(final_index_name), 0);
+ if (p)
+ install_packed_git(the_repository, p);
+ }
if (!from_stdin) {
printf("%s\n", sha1_to_hex(hash));
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 5a5844c153..4ecf909368 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -117,7 +117,7 @@ static void copy_templates(const char *template_dir)
dir = opendir(template_path.buf);
if (!dir) {
- warning(_("templates not found %s"), template_dir);
+ warning(_("templates not found in %s"), template_dir);
goto free_return;
}
diff --git a/builtin/log.c b/builtin/log.c
index a15599f4f0..0583f7f383 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -28,6 +28,7 @@
#include "mailmap.h"
#include "gpg-interface.h"
#include "progress.h"
+#include "commit-slab.h"
#define MAIL_DEFAULT_WRAP 72
@@ -148,6 +149,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
struct decoration_filter decoration_filter = {&decorate_refs_include,
&decorate_refs_exclude};
+ static struct revision_sources revision_sources;
const struct option builtin_log_options[] = {
OPT__QUIET(&quiet, N_("suppress diff output")),
@@ -194,8 +196,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
rev->diffopt.filter || rev->diffopt.flags.follow_renames)
rev->always_show_header = 0;
- if (source)
- rev->show_source = 1;
+ if (source) {
+ init_revision_sources(&revision_sources);
+ rev->sources = &revision_sources;
+ }
if (mailmap) {
rev->mailmap = xcalloc(1, sizeof(struct string_list));
@@ -1337,6 +1341,8 @@ static struct commit *get_base_commit(const char *base_commit,
return base;
}
+define_commit_slab(commit_base, int);
+
static void prepare_bases(struct base_tree_info *bases,
struct commit *base,
struct commit **list,
@@ -1345,11 +1351,13 @@ static void prepare_bases(struct base_tree_info *bases,
struct commit *commit;
struct rev_info revs;
struct diff_options diffopt;
+ struct commit_base commit_base;
int i;
if (!base)
return;
+ init_commit_base(&commit_base);
diff_setup(&diffopt);
diffopt.flags.recursive = 1;
diff_setup_done(&diffopt);
@@ -1362,7 +1370,7 @@ static void prepare_bases(struct base_tree_info *bases,
for (i = 0; i < total; i++) {
list[i]->object.flags &= ~UNINTERESTING;
add_pending_object(&revs, &list[i]->object, "rev_list");
- list[i]->util = (void *)1;
+ *commit_base_at(&commit_base, list[i]) = 1;
}
base->object.flags |= UNINTERESTING;
add_pending_object(&revs, &base->object, "base");
@@ -1376,7 +1384,7 @@ static void prepare_bases(struct base_tree_info *bases,
while ((commit = get_revision(&revs)) != NULL) {
struct object_id oid;
struct object_id *patch_id;
- if (commit->util)
+ if (*commit_base_at(&commit_base, commit))
continue;
if (commit_patch_id(commit, &diffopt, &oid, 0))
die(_("cannot get patch id"));
@@ -1385,6 +1393,7 @@ static void prepare_bases(struct base_tree_info *bases,
oidcpy(patch_id, &oid);
bases->nr_patch_id++;
}
+ clear_commit_base(&commit_base);
}
static void print_bases(struct base_tree_info *bases, FILE *file)
@@ -1474,9 +1483,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
N_("output all-zero hash in From header")),
OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
N_("don't include a patch matching a commit upstream")),
- { OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL,
- N_("show patch format instead of default (patch + stat)"),
- PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1},
+ OPT_SET_INT_F('p', "no-stat", &use_patch_format,
+ N_("show patch format instead of default (patch + stat)"),
+ 1, PARSE_OPT_NONEG),
OPT_GROUP(N_("Messaging")),
{ OPTION_CALLBACK, 0, "add-header", NULL, N_("header"),
N_("add email header"), 0, header_callback },
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 967b2b3380..88bb2019ad 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -556,9 +556,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
N_("add the standard git exclusions"),
PARSE_OPT_NOARG, option_parse_exclude_standard },
- { OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
- N_("make the output relative to the project top directory"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
+ OPT_SET_INT_F(0, "full-name", &prefix_len,
+ N_("make the output relative to the project top directory"),
+ 0, PARSE_OPT_NONEG),
OPT_BOOL(0, "recurse-submodules", &recurse_submodules,
N_("recurse through submodules")),
OPT_BOOL(0, "error-unmatch", &error_unmatch,
diff --git a/builtin/merge.c b/builtin/merge.c
index d85f99b781..4a4c09496c 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -35,6 +35,7 @@
#include "string-list.h"
#include "packfile.h"
#include "tag.h"
+#include "alias.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
@@ -214,9 +215,9 @@ static struct option builtin_merge_options[] = {
OPT_BOOL('e', "edit", &option_edit,
N_("edit message before committing")),
OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW),
- { OPTION_SET_INT, 0, "ff-only", &fast_forward, NULL,
- N_("abort if fast-forward is not possible"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, FF_ONLY },
+ OPT_SET_INT_F(0, "ff-only", &fast_forward,
+ N_("abort if fast-forward is not possible"),
+ FF_ONLY, PARSE_OPT_NONEG),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
OPT_BOOL(0, "verify-signatures", &verify_signatures,
N_("verify that the named commit has a valid GPG signature")),
@@ -444,6 +445,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
struct object_id branch_head;
struct strbuf buf = STRBUF_INIT;
struct strbuf bname = STRBUF_INIT;
+ struct merge_remote_desc *desc;
const char *ptr;
char *found_ref;
int len, early;
@@ -516,16 +518,13 @@ static void merge_name(const char *remote, struct strbuf *msg)
strbuf_release(&truname);
}
- if (remote_head->util) {
- struct merge_remote_desc *desc;
- desc = merge_remote_util(remote_head);
- if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
- strbuf_addf(msg, "%s\t\t%s '%s'\n",
- oid_to_hex(&desc->obj->oid),
- type_name(desc->obj->type),
- remote);
- goto cleanup;
- }
+ desc = merge_remote_util(remote_head);
+ if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
+ strbuf_addf(msg, "%s\t\t%s '%s'\n",
+ oid_to_hex(&desc->obj->oid),
+ type_name(desc->obj->type),
+ remote);
+ goto cleanup;
}
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
@@ -933,8 +932,11 @@ static void write_merge_heads(struct commit_list *remoteheads)
for (j = remoteheads; j; j = j->next) {
struct object_id *oid;
struct commit *c = j->item;
- if (c->util && merge_remote_util(c)->obj) {
- oid = &merge_remote_util(c)->obj->oid;
+ struct merge_remote_desc *desc;
+
+ desc = merge_remote_util(c);
+ if (desc && desc->obj) {
+ oid = &desc->obj->oid;
} else {
oid = &c->object.oid;
}
@@ -1184,14 +1186,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
branch = branch_to_free = resolve_refdup("HEAD", 0, &head_oid, NULL);
if (branch)
skip_prefix(branch, "refs/heads/", &branch);
+
+ init_diff_ui_defaults();
+ git_config(git_merge_config, NULL);
+
if (!branch || is_null_oid(&head_oid))
head_commit = NULL;
else
head_commit = lookup_commit_or_die(&head_oid, "HEAD");
- init_diff_ui_defaults();
- git_config(git_merge_config, NULL);
-
if (branch_mergeoptions)
parse_branch_merge_options(branch_mergeoptions);
argc = parse_options(argc, argv, prefix, builtin_merge_options,
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 387ddf85d2..0eb440359d 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -6,6 +6,7 @@
#include "refs.h"
#include "parse-options.h"
#include "sha1-lookup.h"
+#include "commit-slab.h"
#define CUTOFF_DATE_SLOP 86400 /* one day */
@@ -17,11 +18,26 @@ typedef struct rev_name {
int from_tag;
} rev_name;
+define_commit_slab(commit_rev_name, struct rev_name *);
+
static timestamp_t cutoff = TIME_MAX;
+static struct commit_rev_name rev_names;
/* How many generations are maximally preferred over _one_ merge traversal? */
#define MERGE_TRAVERSAL_WEIGHT 65535
+static struct rev_name *get_commit_rev_name(struct commit *commit)
+{
+ struct rev_name **slot = commit_rev_name_peek(&rev_names, commit);
+
+ return slot ? *slot : NULL;
+}
+
+static void set_commit_rev_name(struct commit *commit, struct rev_name *name)
+{
+ *commit_rev_name_at(&rev_names, commit) = name;
+}
+
static int is_better_name(struct rev_name *name,
const char *tip_name,
timestamp_t taggerdate,
@@ -65,7 +81,7 @@ static void name_rev(struct commit *commit,
int generation, int distance, int from_tag,
int deref)
{
- struct rev_name *name = (struct rev_name *)commit->util;
+ struct rev_name *name = get_commit_rev_name(commit);
struct commit_list *parents;
int parent_number = 1;
char *to_free = NULL;
@@ -84,7 +100,7 @@ static void name_rev(struct commit *commit,
if (name == NULL) {
name = xmalloc(sizeof(rev_name));
- commit->util = name;
+ set_commit_rev_name(commit, name);
goto copy_data;
} else if (is_better_name(name, tip_name, taggerdate,
generation, distance, from_tag)) {
@@ -296,7 +312,7 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
if (o->type != OBJ_COMMIT)
return get_exact_ref_match(o);
c = (struct commit *) o;
- n = c->util;
+ n = get_commit_rev_name(c);
if (!n)
return NULL;
@@ -413,6 +429,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
OPT_END(),
};
+ init_commit_rev_name(&rev_names);
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
if (all + transform_stdin + !!argc > 1) {
diff --git a/builtin/notes.c b/builtin/notes.c
index da279cdd34..6981e2d906 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -778,13 +778,13 @@ static int merge(int argc, const char **argv, const char *prefix)
N_("resolve notes conflicts using the given strategy "
"(manual/ours/theirs/union/cat_sort_uniq)")),
OPT_GROUP(N_("Committing unmerged notes")),
- { OPTION_SET_INT, 0, "commit", &do_commit, NULL,
- N_("finalize notes merge by committing unmerged notes"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
+ OPT_SET_INT_F(0, "commit", &do_commit,
+ N_("finalize notes merge by committing unmerged notes"),
+ 1, PARSE_OPT_NONEG),
OPT_GROUP(N_("Aborting notes merge resolution")),
- { OPTION_SET_INT, 0, "abort", &do_abort, NULL,
- N_("abort notes merge"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
+ OPT_SET_INT_F(0, "abort", &do_abort,
+ N_("abort notes merge"),
+ 1, PARSE_OPT_NONEG),
OPT_END()
};
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index e78f3f5220..71056d8294 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3134,18 +3134,18 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
N_("do not create an empty pack output")),
OPT_BOOL(0, "revs", &use_internal_rev_list,
N_("read revision arguments from standard input")),
- { OPTION_SET_INT, 0, "unpacked", &rev_list_unpacked, NULL,
- N_("limit the objects to those that are not yet packed"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
- { OPTION_SET_INT, 0, "all", &rev_list_all, NULL,
- N_("include objects reachable from any reference"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
- { OPTION_SET_INT, 0, "reflog", &rev_list_reflog, NULL,
- N_("include objects referred by reflog entries"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
- { OPTION_SET_INT, 0, "indexed-objects", &rev_list_index, NULL,
- N_("include objects referred to by the index"),
- PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
+ OPT_SET_INT_F(0, "unpacked", &rev_list_unpacked,
+ N_("limit the objects to those that are not yet packed"),
+ 1, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "all", &rev_list_all,
+ N_("include objects reachable from any reference"),
+ 1, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "reflog", &rev_list_reflog,
+ N_("include objects referred by reflog entries"),
+ 1, PARSE_OPT_NONEG),
+ OPT_SET_INT_F(0, "indexed-objects", &rev_list_index,
+ N_("include objects referred to by the index"),
+ 1, PARSE_OPT_NONEG),
OPT_BOOL(0, "stdout", &pack_to_stdout,
N_("output pack to stdout")),
OPT_BOOL(0, "include-tag", &include_tag,
diff --git a/builtin/pull.c b/builtin/pull.c
index 1f2ecf3a88..49cc3beb4c 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -673,7 +673,7 @@ static const char *get_upstream_branch(const char *remote)
}
/**
- * Derives the remote tracking branch from the remote and refspec.
+ * Derives the remote-tracking branch from the remote and refspec.
*
* FIXME: The current implementation assumes the default mapping of
* refs/heads/<branch_name> to refs/remotes/<remote_name>/<branch_name>.
@@ -711,7 +711,7 @@ static const char *get_tracking_branch(const char *remote, const char *refspec)
/**
* Given the repo and refspecs, sets fork_point to the point at which the
- * current branch forked from its remote tracking branch. Returns 0 on success,
+ * current branch forked from its remote-tracking branch. Returns 0 on success,
* -1 on failure.
*/
static int get_rebase_fork_point(struct object_id *fork_point, const char *repo,
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 55c0b90441..4f49e96bfd 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -282,6 +282,10 @@ static int try_difference(const char *arg)
struct commit *a, *b;
a = lookup_commit_reference(&start_oid);
b = lookup_commit_reference(&end_oid);
+ if (!a || !b) {
+ *dotdot = '.';
+ return 0;
+ }
exclude = get_merge_bases(a, b);
while (exclude) {
struct commit *commit = pop_commit(&exclude);
@@ -328,12 +332,12 @@ static int try_parent_shorthands(const char *arg)
return 0;
*dotdot = 0;
- if (get_oid_committish(arg, &oid)) {
+ if (get_oid_committish(arg, &oid) ||
+ !(commit = lookup_commit_reference(&oid))) {
*dotdot = '^';
return 0;
}
- commit = lookup_commit_reference(&oid);
if (exclude_parent &&
exclude_parent > commit_list_count(commit->parents)) {
*dotdot = '^';
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 6c2148b71d..f2e985c00a 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -7,6 +7,7 @@
#include "argv-array.h"
#include "parse-options.h"
#include "dir.h"
+#include "commit-slab.h"
static const char* show_branch_usage[] = {
N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
@@ -21,6 +22,11 @@ static int showbranch_use_color = -1;
static struct argv_array default_args = ARGV_ARRAY_INIT;
+/*
+ * TODO: convert this use of commit->object.flags to commit-slab
+ * instead to store a pointer to ref name directly. Then use the same
+ * UNINTERESTING definition from revision.h here.
+ */
#define UNINTERESTING 01
#define REV_SHIFT 2
@@ -59,15 +65,27 @@ struct commit_name {
int generation; /* how many parents away from head_name */
};
+define_commit_slab(commit_name_slab, struct commit_name *);
+static struct commit_name_slab name_slab;
+
+static struct commit_name *commit_to_name(struct commit *commit)
+{
+ return *commit_name_slab_at(&name_slab, commit);
+}
+
+
/* Name the commit as nth generation ancestor of head_name;
* we count only the first-parent relationship for naming purposes.
*/
static void name_commit(struct commit *commit, const char *head_name, int nth)
{
struct commit_name *name;
- if (!commit->util)
- commit->util = xmalloc(sizeof(struct commit_name));
- name = commit->util;
+
+ name = *commit_name_slab_at(&name_slab, commit);
+ if (!name) {
+ name = xmalloc(sizeof(*name));
+ *commit_name_slab_at(&name_slab, commit) = name;
+ }
name->head_name = head_name;
name->generation = nth;
}
@@ -79,8 +97,8 @@ static void name_commit(struct commit *commit, const char *head_name, int nth)
*/
static void name_parent(struct commit *commit, struct commit *parent)
{
- struct commit_name *commit_name = commit->util;
- struct commit_name *parent_name = parent->util;
+ struct commit_name *commit_name = commit_to_name(commit);
+ struct commit_name *parent_name = commit_to_name(parent);
if (!commit_name)
return;
if (!parent_name ||
@@ -94,12 +112,12 @@ static int name_first_parent_chain(struct commit *c)
int i = 0;
while (c) {
struct commit *p;
- if (!c->util)
+ if (!commit_to_name(c))
break;
if (!c->parents)
break;
p = c->parents->item;
- if (!p->util) {
+ if (!commit_to_name(p)) {
name_parent(c, p);
i++;
}
@@ -122,7 +140,7 @@ static void name_commits(struct commit_list *list,
/* First give names to the given heads */
for (cl = list; cl; cl = cl->next) {
c = cl->item;
- if (c->util)
+ if (commit_to_name(c))
continue;
for (i = 0; i < num_rev; i++) {
if (rev[i] == c) {
@@ -148,9 +166,9 @@ static void name_commits(struct commit_list *list,
struct commit_name *n;
int nth;
c = cl->item;
- if (!c->util)
+ if (!commit_to_name(c))
continue;
- n = c->util;
+ n = commit_to_name(c);
parents = c->parents;
nth = 0;
while (parents) {
@@ -158,7 +176,7 @@ static void name_commits(struct commit_list *list,
struct strbuf newname = STRBUF_INIT;
parents = parents->next;
nth++;
- if (p->util)
+ if (commit_to_name(p))
continue;
switch (n->generation) {
case 0:
@@ -271,7 +289,7 @@ static void show_one_commit(struct commit *commit, int no_name)
{
struct strbuf pretty = STRBUF_INIT;
const char *pretty_str = "(unavailable)";
- struct commit_name *name = commit->util;
+ struct commit_name *name = commit_to_name(commit);
if (commit->object.parsed) {
pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
@@ -660,6 +678,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
OPT_END()
};
+ init_commit_name_slab(&name_slab);
+
git_config(git_show_branch_config, NULL);
/* If nothing is specified, try the default first */
diff --git a/builtin/show-index.c b/builtin/show-index.c
new file mode 100644
index 0000000000..a6e678809e
--- /dev/null
+++ b/builtin/show-index.c
@@ -0,0 +1,86 @@
+#include "builtin.h"
+#include "cache.h"
+#include "pack.h"
+
+static const char show_index_usage[] =
+"git show-index";
+
+int cmd_show_index(int argc, const char **argv, const char *prefix)
+{
+ int i;
+ unsigned nr;
+ unsigned int version;
+ static unsigned int top_index[256];
+
+ if (argc != 1)
+ usage(show_index_usage);
+ if (fread(top_index, 2 * 4, 1, stdin) != 1)
+ die("unable to read header");
+ if (top_index[0] == htonl(PACK_IDX_SIGNATURE)) {
+ version = ntohl(top_index[1]);
+ if (version < 2 || version > 2)
+ die("unknown index version");
+ if (fread(top_index, 256 * 4, 1, stdin) != 1)
+ die("unable to read index");
+ } else {
+ version = 1;
+ if (fread(&top_index[2], 254 * 4, 1, stdin) != 1)
+ die("unable to read index");
+ }
+ nr = 0;
+ for (i = 0; i < 256; i++) {
+ unsigned n = ntohl(top_index[i]);
+ if (n < nr)
+ die("corrupt index file");
+ nr = n;
+ }
+ if (version == 1) {
+ for (i = 0; i < nr; i++) {
+ unsigned int offset, entry[6];
+
+ if (fread(entry, 4 + 20, 1, stdin) != 1)
+ die("unable to read entry %u/%u", i, nr);
+ offset = ntohl(entry[0]);
+ printf("%u %s\n", offset, sha1_to_hex((void *)(entry+1)));
+ }
+ } else {
+ unsigned off64_nr = 0;
+ struct {
+ unsigned char sha1[20];
+ uint32_t crc;
+ uint32_t off;
+ } *entries;
+ ALLOC_ARRAY(entries, nr);
+ for (i = 0; i < nr; i++)
+ if (fread(entries[i].sha1, 20, 1, stdin) != 1)
+ die("unable to read sha1 %u/%u", i, nr);
+ for (i = 0; i < nr; i++)
+ if (fread(&entries[i].crc, 4, 1, stdin) != 1)
+ die("unable to read crc %u/%u", i, nr);
+ for (i = 0; i < nr; i++)
+ if (fread(&entries[i].off, 4, 1, stdin) != 1)
+ die("unable to read 32b offset %u/%u", i, nr);
+ for (i = 0; i < nr; i++) {
+ uint64_t offset;
+ uint32_t off = ntohl(entries[i].off);
+ if (!(off & 0x80000000)) {
+ offset = off;
+ } else {
+ uint32_t off64[2];
+ if ((off & 0x7fffffff) != off64_nr)
+ die("inconsistent 64b offset index");
+ if (fread(off64, 8, 1, stdin) != 1)
+ die("unable to read 64b offset %u", off64_nr);
+ offset = (((uint64_t)ntohl(off64[0])) << 32) |
+ ntohl(off64[1]);
+ off64_nr++;
+ }
+ printf("%" PRIuMAX " %s (%08"PRIx32")\n",
+ (uintmax_t) offset,
+ sha1_to_hex(entries[i].sha1),
+ ntohl(entries[i].crc));
+ }
+ free(entries);
+ }
+ return 0;
+}
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 7a752dbf9d..20ae9191ca 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -441,6 +441,149 @@ static void for_each_listed_submodule(const struct module_list *list,
fn(list->entries[i], cb_data);
}
+struct cb_foreach {
+ int argc;
+ const char **argv;
+ const char *prefix;
+ int quiet;
+ int recursive;
+};
+#define CB_FOREACH_INIT { 0 }
+
+static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
+ void *cb_data)
+{
+ struct cb_foreach *info = cb_data;
+ const char *path = list_item->name;
+ const struct object_id *ce_oid = &list_item->oid;
+
+ const struct submodule *sub;
+ struct child_process cp = CHILD_PROCESS_INIT;
+ char *displaypath;
+
+ displaypath = get_submodule_displaypath(path, info->prefix);
+
+ sub = submodule_from_path(the_repository, &null_oid, path);
+
+ if (!sub)
+ die(_("No url found for submodule path '%s' in .gitmodules"),
+ displaypath);
+
+ if (!is_submodule_populated_gently(path, NULL))
+ goto cleanup;
+
+ prepare_submodule_repo_env(&cp.env_array);
+
+ /*
+ * For the purpose of executing <command> in the submodule,
+ * separate shell is used for the purpose of running the
+ * child process.
+ */
+ cp.use_shell = 1;
+ cp.dir = path;
+
+ /*
+ * NEEDSWORK: the command currently has access to the variables $name,
+ * $sm_path, $displaypath, $sha1 and $toplevel only when the command
+ * contains a single argument. This is done for maintaining a faithful
+ * translation from shell script.
+ */
+ if (info->argc == 1) {
+ char *toplevel = xgetcwd();
+ struct strbuf sb = STRBUF_INIT;
+
+ argv_array_pushf(&cp.env_array, "name=%s", sub->name);
+ argv_array_pushf(&cp.env_array, "sm_path=%s", path);
+ argv_array_pushf(&cp.env_array, "displaypath=%s", displaypath);
+ argv_array_pushf(&cp.env_array, "sha1=%s",
+ oid_to_hex(ce_oid));
+ argv_array_pushf(&cp.env_array, "toplevel=%s", toplevel);
+
+ /*
+ * Since the path variable was accessible from the script
+ * before porting, it is also made available after porting.
+ * The environment variable "PATH" has a very special purpose
+ * on windows. And since environment variables are
+ * case-insensitive in windows, it interferes with the
+ * existing PATH variable. Hence, to avoid that, we expose
+ * path via the args argv_array and not via env_array.
+ */
+ sq_quote_buf(&sb, path);
+ argv_array_pushf(&cp.args, "path=%s; %s",
+ sb.buf, info->argv[0]);
+ strbuf_release(&sb);
+ free(toplevel);
+ } else {
+ argv_array_pushv(&cp.args, info->argv);
+ }
+
+ if (!info->quiet)
+ printf(_("Entering '%s'\n"), displaypath);
+
+ if (info->argv[0] && run_command(&cp))
+ die(_("run_command returned non-zero status for %s\n."),
+ displaypath);
+
+ if (info->recursive) {
+ struct child_process cpr = CHILD_PROCESS_INIT;
+
+ cpr.git_cmd = 1;
+ cpr.dir = path;
+ prepare_submodule_repo_env(&cpr.env_array);
+
+ argv_array_pushl(&cpr.args, "--super-prefix", NULL);
+ argv_array_pushf(&cpr.args, "%s/", displaypath);
+ argv_array_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
+ NULL);
+
+ if (info->quiet)
+ argv_array_push(&cpr.args, "--quiet");
+
+ argv_array_pushv(&cpr.args, info->argv);
+
+ if (run_command(&cpr))
+ die(_("run_command returned non-zero status while"
+ "recursing in the nested submodules of %s\n."),
+ displaypath);
+ }
+
+cleanup:
+ free(displaypath);
+}
+
+static int module_foreach(int argc, const char **argv, const char *prefix)
+{
+ struct cb_foreach info = CB_FOREACH_INIT;
+ struct pathspec pathspec;
+ struct module_list list = MODULE_LIST_INIT;
+
+ struct option module_foreach_options[] = {
+ OPT__QUIET(&info.quiet, N_("Suppress output of entering each submodule command")),
+ OPT_BOOL(0, "recursive", &info.recursive,
+ N_("Recurse into nested submodules")),
+ OPT_END()
+ };
+
+ const char *const git_submodule_helper_usage[] = {
+ N_("git submodule--helper foreach [--quiet] [--recursive] <command>"),
+ NULL
+ };
+
+ argc = parse_options(argc, argv, prefix, module_foreach_options,
+ git_submodule_helper_usage, PARSE_OPT_KEEP_UNKNOWN);
+
+ if (module_list_compute(0, NULL, prefix, &pathspec, &list) < 0)
+ return 1;
+
+ info.argc = argc;
+ info.argv = argv;
+ info.prefix = prefix;
+
+ for_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);
+
+ return 0;
+}
+
struct init_cb {
const char *prefix;
unsigned int flags;
@@ -1877,6 +2020,7 @@ static struct cmd_struct commands[] = {
{"relative-path", resolve_relative_path, 0},
{"resolve-relative-url", resolve_relative_url, 0},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
+ {"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
{"init", module_init, SUPPORT_SUPER_PREFIX},
{"status", module_status, SUPPORT_SUPER_PREFIX},
{"print-default-remote", print_default_remote, 0},
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 4b4714b3fd..4fa3c0a86f 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -311,11 +311,12 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
static const char *parse_cmd_option(struct strbuf *input, const char *next)
{
- if (!strncmp(next, "no-deref", 8) && next[8] == line_termination)
+ const char *rest;
+ if (skip_prefix(next, "no-deref", &rest) && *rest == line_termination)
update_flags |= REF_NO_DEREF;
else
die("option unknown: %s", next);
- return next + 8;
+ return rest;
}
static void update_refs_stdin(struct ref_transaction *transaction)
@@ -332,16 +333,16 @@ static void update_refs_stdin(struct ref_transaction *transaction)
die("empty command in input");
else if (isspace(*next))
die("whitespace before command: %s", next);
- else if (starts_with(next, "update "))
- next = parse_cmd_update(transaction, &input, next + 7);
- else if (starts_with(next, "create "))
- next = parse_cmd_create(transaction, &input, next + 7);
- else if (starts_with(next, "delete "))
- next = parse_cmd_delete(transaction, &input, next + 7);
- else if (starts_with(next, "verify "))
- next = parse_cmd_verify(transaction, &input, next + 7);
- else if (starts_with(next, "option "))
- next = parse_cmd_option(&input, next + 7);
+ else if (skip_prefix(next, "update ", &next))
+ next = parse_cmd_update(transaction, &input, next);
+ else if (skip_prefix(next, "create ", &next))
+ next = parse_cmd_create(transaction, &input, next);
+ else if (skip_prefix(next, "delete ", &next))
+ next = parse_cmd_delete(transaction, &input, next);
+ else if (skip_prefix(next, "verify ", &next))
+ next = parse_cmd_verify(transaction, &input, next);
+ else if (skip_prefix(next, "option ", &next))
+ next = parse_cmd_option(&input, next);
else
die("unknown command: %s", next);