2006-12-19 23:34:12 +01:00
|
|
|
#include "builtin.h"
|
2017-06-14 20:07:36 +02:00
|
|
|
#include "config.h"
|
2023-03-21 07:26:03 +01:00
|
|
|
#include "environment.h"
|
2018-04-10 23:26:18 +02:00
|
|
|
#include "exec-cmd.h"
|
2023-03-21 07:25:54 +01:00
|
|
|
#include "gettext.h"
|
2010-09-01 04:29:08 +02:00
|
|
|
#include "help.h"
|
2023-04-11 09:41:59 +02:00
|
|
|
#include "pager.h"
|
2023-05-16 08:33:56 +02:00
|
|
|
#include "read-cache-ll.h"
|
2009-01-28 08:38:14 +01:00
|
|
|
#include "run-command.h"
|
2018-05-20 20:40:06 +02:00
|
|
|
#include "alias.h"
|
2023-02-24 01:09:33 +01:00
|
|
|
#include "replace-object.h"
|
2023-03-21 07:26:05 +01:00
|
|
|
#include "setup.h"
|
2023-05-06 06:15:29 +02:00
|
|
|
#include "attr.h"
|
2020-04-30 21:48:50 +02:00
|
|
|
#include "shallow.h"
|
2023-04-11 05:00:38 +02:00
|
|
|
#include "trace.h"
|
|
|
|
#include "trace2.h"
|
2005-11-16 00:31:25 +01:00
|
|
|
|
2018-03-24 21:35:18 +01:00
|
|
|
#define RUN_SETUP (1<<0)
|
|
|
|
#define RUN_SETUP_GENTLY (1<<1)
|
|
|
|
#define USE_PAGER (1<<2)
|
|
|
|
/*
|
|
|
|
* require working tree to be present -- anything uses this needs
|
|
|
|
* RUN_SETUP for reading from the configuration file.
|
|
|
|
*/
|
|
|
|
#define NEED_WORK_TREE (1<<3)
|
read-tree: add "--super-prefix" option, eliminate global
The "--super-prefix" option to "git" was initially added in [1] for
use with "ls-files"[2], and shortly thereafter "submodule--helper"[3]
and "grep"[4]. It wasn't until [5] that "read-tree" made use of it.
At the time [5] made sense, but since then we've made "ls-files"
recurse in-process in [6], "grep" in [7], and finally
"submodule--helper" in the preceding commits.
Let's also remove it from "read-tree", which allows us to remove the
option to "git" itself.
We can do this because the only remaining user of it is the submodule
API, which will now invoke "read-tree" with its new "--super-prefix"
option. It will only do so when the "submodule_move_head()" function
is called.
That "submodule_move_head()" function was then only invoked by
"read-tree" itself, but now rather than setting an environment
variable to pass "--super-prefix" between cmd_read_tree() we:
- Set a new "super_prefix" in "struct unpack_trees_options". The
"super_prefixed()" function in "unpack-trees.c" added in [5] will now
use this, rather than get_super_prefix() looking up the environment
variable we set earlier in the same process.
- Add the same field to the "struct checkout", which is only needed to
ferry the "super_prefix" in the "struct unpack_trees_options" all the
way down to the "entry.c" callers of "submodule_move_head()".
Those calls which used the super prefix all originated in
"cmd_read_tree()". The only other caller is the "unlink_entry()"
caller in "builtin/checkout.c", which now passes a "NULL".
1. 74866d75793 (git: make super-prefix option, 2016-10-07)
2. e77aa336f11 (ls-files: optionally recurse into submodules, 2016-10-07)
3. 89c86265576 (submodule helper: support super prefix, 2016-12-08)
4. 0281e487fd9 (grep: optionally recurse into submodules, 2016-12-16)
5. 3d415425c7b (unpack-trees: support super-prefix option, 2017-01-17)
6. 188dce131fa (ls-files: use repository object, 2017-06-22)
7. f9ee2fcdfa0 (grep: recurse in-process using 'struct repository', 2017-08-02)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-20 13:39:56 +01:00
|
|
|
#define DELAY_PAGER_CONFIG (1<<4)
|
|
|
|
#define NO_PARSEOPT (1<<5) /* parse-options is not used */
|
2018-03-24 21:35:18 +01:00
|
|
|
|
|
|
|
struct cmd_struct {
|
|
|
|
const char *cmd;
|
|
|
|
int (*fn)(int, const char **, const char *);
|
2018-03-24 21:35:19 +01:00
|
|
|
unsigned int option;
|
2018-03-24 21:35:18 +01:00
|
|
|
};
|
|
|
|
|
2006-07-30 23:42:25 +02:00
|
|
|
const char git_usage_string[] =
|
2022-03-31 23:27:09 +02:00
|
|
|
N_("git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
|
2018-02-13 14:19:15 +01:00
|
|
|
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
|
git: add -P as a short option for --no-pager
It is possible to configure 'less', the pager, to use an alternate
screen to show the content, for example, by setting LESS=RS in the
environment. When it is closed in this configuration, it switches
back to the original screen, and all content is gone.
It is not uncommon to request that the output remains visible in
the terminal. For this, the option --no-pager can be used. But
it is a bit cumbersome to type, even when command completion is
available. Provide a short option, -P, to make the option more
easily accessible.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-03 19:15:08 +02:00
|
|
|
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
|
2018-02-13 14:19:15 +01:00
|
|
|
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
|
read-tree: add "--super-prefix" option, eliminate global
The "--super-prefix" option to "git" was initially added in [1] for
use with "ls-files"[2], and shortly thereafter "submodule--helper"[3]
and "grep"[4]. It wasn't until [5] that "read-tree" made use of it.
At the time [5] made sense, but since then we've made "ls-files"
recurse in-process in [6], "grep" in [7], and finally
"submodule--helper" in the preceding commits.
Let's also remove it from "read-tree", which allows us to remove the
option to "git" itself.
We can do this because the only remaining user of it is the submodule
API, which will now invoke "read-tree" with its new "--super-prefix"
option. It will only do so when the "submodule_move_head()" function
is called.
That "submodule_move_head()" function was then only invoked by
"read-tree" itself, but now rather than setting an environment
variable to pass "--super-prefix" between cmd_read_tree() we:
- Set a new "super_prefix" in "struct unpack_trees_options". The
"super_prefixed()" function in "unpack-trees.c" added in [5] will now
use this, rather than get_super_prefix() looking up the environment
variable we set earlier in the same process.
- Add the same field to the "struct checkout", which is only needed to
ferry the "super_prefix" in the "struct unpack_trees_options" all the
way down to the "entry.c" callers of "submodule_move_head()".
Those calls which used the super prefix all originated in
"cmd_read_tree()". The only other caller is the "unlink_entry()"
caller in "builtin/checkout.c", which now passes a "NULL".
1. 74866d75793 (git: make super-prefix option, 2016-10-07)
2. e77aa336f11 (ls-files: optionally recurse into submodules, 2016-10-07)
3. 89c86265576 (submodule helper: support super prefix, 2016-12-08)
4. 0281e487fd9 (grep: optionally recurse into submodules, 2016-12-16)
5. 3d415425c7b (unpack-trees: support super-prefix option, 2017-01-17)
6. 188dce131fa (ls-files: use repository object, 2017-06-22)
7. f9ee2fcdfa0 (grep: recurse in-process using 'struct repository', 2017-08-02)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-12-20 13:39:56 +01:00
|
|
|
" [--config-env=<name>=<envvar>] <command> [<args>]");
|
2006-07-30 23:42:25 +02:00
|
|
|
|
2008-06-05 23:15:36 +02:00
|
|
|
const char git_more_info_string[] =
|
2014-08-30 21:56:01 +02:00
|
|
|
N_("'git help -a' and 'git help -g' list available subcommands and some\n"
|
2013-04-03 00:39:48 +02:00
|
|
|
"concept guides. See 'git help <command>' or 'git help <concept>'\n"
|
2019-05-16 00:47:08 +02:00
|
|
|
"to read about a specific subcommand or concept.\n"
|
|
|
|
"See 'git help git' for an overview of the system.");
|
2008-06-05 23:15:36 +02:00
|
|
|
|
Allow per-command pager config
There is great debate over whether some commands should set
up a pager automatically. This patch allows individuals to
set their own pager preferences for each command, overriding
the default. For example, to disable the pager for git
status:
git config pager.status false
If "--pager" or "--no-pager" is specified on the command
line, it takes precedence over the config option.
There are two caveats:
- you can turn on the pager for plumbing commands.
Combined with "core.pager = always", this will probably
break a lot of things. Don't do it.
- This only works for builtin commands. The reason is
somewhat complex:
Calling git_config before we do setup_git_directory
has bad side effects, because it wants to know where
the git_dir is to find ".git/config". Unfortunately,
we cannot call setup_git_directory indiscriminately,
because some builtins (like "init") break if we do.
For builtins, this is OK, since we can just wait until
after we call setup_git_directory. But for aliases, we
don't know until we expand (recursively) which command
we're doing. This should not be a huge problem for
aliases, which can simply use "--pager" or "--no-pager"
in the alias as appropriate.
For external commands, however, we don't know we even
have an external command until we exec it, and by then
it is too late to check the config.
An alternative approach would be to have a config mode
where we don't bother looking at .git/config, but only
at the user and system config files. This would make the
behavior consistent across builtins, aliases, and
external commands, at the cost of not allowing per-repo
pager config for at all.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-03 13:46:57 +02:00
|
|
|
static int use_pager = -1;
|
2014-06-08 11:37:10 +02:00
|
|
|
|
2018-05-20 20:39:58 +02:00
|
|
|
static void list_builtins(struct string_list *list, unsigned int exclude_option);
|
2017-05-30 07:18:43 +02:00
|
|
|
|
2018-05-20 20:40:07 +02:00
|
|
|
static void exclude_helpers_from_list(struct string_list *list)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while (i < list->nr) {
|
|
|
|
if (strstr(list->items[i].string, "--"))
|
|
|
|
unsorted_string_list_delete_item(list, i, 0);
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-20 20:39:57 +02:00
|
|
|
static int match_token(const char *spec, int len, const char *token)
|
|
|
|
{
|
|
|
|
int token_len = strlen(token);
|
|
|
|
|
|
|
|
return len == token_len && !strncmp(spec, token, token_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int list_cmds(const char *spec)
|
|
|
|
{
|
2018-05-20 20:39:58 +02:00
|
|
|
struct string_list list = STRING_LIST_INIT_DUP;
|
|
|
|
int i;
|
2019-03-20 19:03:26 +01:00
|
|
|
int nongit;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the repository so we can pick up any repo-level config (like
|
|
|
|
* completion.commands).
|
|
|
|
*/
|
|
|
|
setup_git_directory_gently(&nongit);
|
2018-05-20 20:39:58 +02:00
|
|
|
|
2018-05-20 20:39:57 +02:00
|
|
|
while (*spec) {
|
|
|
|
const char *sep = strchrnul(spec, ',');
|
|
|
|
int len = sep - spec;
|
|
|
|
|
|
|
|
if (match_token(spec, len, "builtins"))
|
2018-05-20 20:39:58 +02:00
|
|
|
list_builtins(&list, 0);
|
2018-05-20 20:39:59 +02:00
|
|
|
else if (match_token(spec, len, "main"))
|
|
|
|
list_all_main_cmds(&list);
|
|
|
|
else if (match_token(spec, len, "others"))
|
|
|
|
list_all_other_cmds(&list);
|
2018-05-20 20:40:07 +02:00
|
|
|
else if (match_token(spec, len, "nohelpers"))
|
|
|
|
exclude_helpers_from_list(&list);
|
2018-05-20 20:40:08 +02:00
|
|
|
else if (match_token(spec, len, "alias"))
|
|
|
|
list_aliases(&list);
|
2018-05-20 20:40:09 +02:00
|
|
|
else if (match_token(spec, len, "config"))
|
|
|
|
list_cmds_by_config(&list);
|
2018-05-20 20:40:00 +02:00
|
|
|
else if (len > 5 && !strncmp(spec, "list-", 5)) {
|
|
|
|
struct strbuf sb = STRBUF_INIT;
|
|
|
|
|
|
|
|
strbuf_add(&sb, spec + 5, len - 5);
|
|
|
|
list_cmds_by_category(&list, sb.buf);
|
|
|
|
strbuf_release(&sb);
|
|
|
|
}
|
2018-05-20 20:39:57 +02:00
|
|
|
else
|
|
|
|
die(_("unsupported command listing type '%s'"), spec);
|
|
|
|
spec += len;
|
|
|
|
if (*spec == ',')
|
|
|
|
spec++;
|
|
|
|
}
|
2018-05-20 20:39:58 +02:00
|
|
|
for (i = 0; i < list.nr; i++)
|
|
|
|
puts(list.items[i].string);
|
|
|
|
string_list_clear(&list, 0);
|
2018-05-20 20:39:57 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2017-05-30 07:18:43 +02:00
|
|
|
|
2018-12-09 11:25:21 +01:00
|
|
|
static void commit_pager_choice(void)
|
|
|
|
{
|
Allow per-command pager config
There is great debate over whether some commands should set
up a pager automatically. This patch allows individuals to
set their own pager preferences for each command, overriding
the default. For example, to disable the pager for git
status:
git config pager.status false
If "--pager" or "--no-pager" is specified on the command
line, it takes precedence over the config option.
There are two caveats:
- you can turn on the pager for plumbing commands.
Combined with "core.pager = always", this will probably
break a lot of things. Don't do it.
- This only works for builtin commands. The reason is
somewhat complex:
Calling git_config before we do setup_git_directory
has bad side effects, because it wants to know where
the git_dir is to find ".git/config". Unfortunately,
we cannot call setup_git_directory indiscriminately,
because some builtins (like "init") break if we do.
For builtins, this is OK, since we can just wait until
after we call setup_git_directory. But for aliases, we
don't know until we expand (recursively) which command
we're doing. This should not be a huge problem for
aliases, which can simply use "--pager" or "--no-pager"
in the alias as appropriate.
For external commands, however, we don't know we even
have an external command until we exec it, and by then
it is too late to check the config.
An alternative approach would be to have a config mode
where we don't bother looking at .git/config, but only
at the user and system config files. This would make the
behavior consistent across builtins, aliases, and
external commands, at the cost of not allowing per-repo
pager config for at all.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-03 13:46:57 +02:00
|
|
|
switch (use_pager) {
|
|
|
|
case 0:
|
|
|
|
setenv("GIT_PAGER", "cat", 1);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
setup_pager();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 21:40:51 +02:00
|
|
|
void setup_auto_pager(const char *cmd, int def)
|
|
|
|
{
|
|
|
|
if (use_pager != -1 || pager_in_use())
|
|
|
|
return;
|
|
|
|
use_pager = check_pager_config(cmd);
|
|
|
|
if (use_pager == -1)
|
|
|
|
use_pager = def;
|
|
|
|
commit_pager_choice();
|
|
|
|
}
|
|
|
|
|
2009-05-01 11:06:36 +02:00
|
|
|
static int handle_options(const char ***argv, int *argc, int *envchanged)
|
2006-07-24 14:10:45 +02:00
|
|
|
{
|
2011-05-25 00:50:35 +02:00
|
|
|
const char **orig_argv = *argv;
|
2006-07-24 14:10:45 +02:00
|
|
|
|
|
|
|
while (*argc > 0) {
|
|
|
|
const char *cmd = (*argv)[0];
|
|
|
|
if (cmd[0] != '-')
|
|
|
|
break;
|
|
|
|
|
2006-07-25 20:24:22 +02:00
|
|
|
/*
|
|
|
|
* For legacy reasons, the "version" and "help"
|
|
|
|
* commands can be written with "--" prepended
|
|
|
|
* to make them look like flags.
|
|
|
|
*/
|
2022-03-31 23:27:09 +02:00
|
|
|
if (!strcmp(cmd, "--help") || !strcmp(cmd, "-h") ||
|
|
|
|
!strcmp(cmd, "--version") || !strcmp(cmd, "-v"))
|
2006-07-25 20:24:22 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check remaining flags.
|
|
|
|
*/
|
use skip_prefix to avoid magic numbers
It's a common idiom to match a prefix and then skip past it
with a magic number, like:
if (starts_with(foo, "bar"))
foo += 3;
This is easy to get wrong, since you have to count the
prefix string yourself, and there's no compiler check if the
string changes. We can use skip_prefix to avoid the magic
numbers here.
Note that some of these conversions could be much shorter.
For example:
if (starts_with(arg, "--foo=")) {
bar = arg + 6;
continue;
}
could become:
if (skip_prefix(arg, "--foo=", &bar))
continue;
However, I have left it as:
if (skip_prefix(arg, "--foo=", &v)) {
bar = v;
continue;
}
to visually match nearby cases which need to actually
process the string. Like:
if (skip_prefix(arg, "--foo=", &v)) {
bar = atoi(v);
continue;
}
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-18 21:47:50 +02:00
|
|
|
if (skip_prefix(cmd, "--exec-path", &cmd)) {
|
2006-07-25 20:24:22 +02:00
|
|
|
if (*cmd == '=')
|
2018-04-10 17:05:44 +02:00
|
|
|
git_set_exec_path(cmd + 1);
|
2006-07-25 20:24:22 +02:00
|
|
|
else {
|
|
|
|
puts(git_exec_path());
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_query_");
|
2006-07-25 20:24:22 +02:00
|
|
|
exit(0);
|
|
|
|
}
|
2009-04-05 04:15:16 +02:00
|
|
|
} else if (!strcmp(cmd, "--html-path")) {
|
|
|
|
puts(system_path(GIT_HTML_PATH));
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_query_");
|
2009-04-05 04:15:16 +02:00
|
|
|
exit(0);
|
2011-05-01 10:16:25 +02:00
|
|
|
} else if (!strcmp(cmd, "--man-path")) {
|
|
|
|
puts(system_path(GIT_MAN_PATH));
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_query_");
|
2011-05-01 10:16:25 +02:00
|
|
|
exit(0);
|
|
|
|
} else if (!strcmp(cmd, "--info-path")) {
|
|
|
|
puts(system_path(GIT_INFO_PATH));
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_query_");
|
2011-05-01 10:16:25 +02:00
|
|
|
exit(0);
|
2006-07-25 20:24:22 +02:00
|
|
|
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
|
Allow per-command pager config
There is great debate over whether some commands should set
up a pager automatically. This patch allows individuals to
set their own pager preferences for each command, overriding
the default. For example, to disable the pager for git
status:
git config pager.status false
If "--pager" or "--no-pager" is specified on the command
line, it takes precedence over the config option.
There are two caveats:
- you can turn on the pager for plumbing commands.
Combined with "core.pager = always", this will probably
break a lot of things. Don't do it.
- This only works for builtin commands. The reason is
somewhat complex:
Calling git_config before we do setup_git_directory
has bad side effects, because it wants to know where
the git_dir is to find ".git/config". Unfortunately,
we cannot call setup_git_directory indiscriminately,
because some builtins (like "init") break if we do.
For builtins, this is OK, since we can just wait until
after we call setup_git_directory. But for aliases, we
don't know until we expand (recursively) which command
we're doing. This should not be a huge problem for
aliases, which can simply use "--pager" or "--no-pager"
in the alias as appropriate.
For external commands, however, we don't know we even
have an external command until we exec it, and by then
it is too late to check the config.
An alternative approach would be to have a config mode
where we don't bother looking at .git/config, but only
at the user and system config files. This would make the
behavior consistent across builtins, aliases, and
external commands, at the cost of not allowing per-repo
pager config for at all.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-03 13:46:57 +02:00
|
|
|
use_pager = 1;
|
git: add -P as a short option for --no-pager
It is possible to configure 'less', the pager, to use an alternate
screen to show the content, for example, by setting LESS=RS in the
environment. When it is closed in this configuration, it switches
back to the original screen, and all content is gone.
It is not uncommon to request that the output remains visible in
the terminal. For this, the option --no-pager can be used. But
it is a bit cumbersome to type, even when command completion is
available. Provide a short option, -P, to make the option more
easily accessible.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-03 19:15:08 +02:00
|
|
|
} else if (!strcmp(cmd, "-P") || !strcmp(cmd, "--no-pager")) {
|
Allow per-command pager config
There is great debate over whether some commands should set
up a pager automatically. This patch allows individuals to
set their own pager preferences for each command, overriding
the default. For example, to disable the pager for git
status:
git config pager.status false
If "--pager" or "--no-pager" is specified on the command
line, it takes precedence over the config option.
There are two caveats:
- you can turn on the pager for plumbing commands.
Combined with "core.pager = always", this will probably
break a lot of things. Don't do it.
- This only works for builtin commands. The reason is
somewhat complex:
Calling git_config before we do setup_git_directory
has bad side effects, because it wants to know where
the git_dir is to find ".git/config". Unfortunately,
we cannot call setup_git_directory indiscriminately,
because some builtins (like "init") break if we do.
For builtins, this is OK, since we can just wait until
after we call setup_git_directory. But for aliases, we
don't know until we expand (recursively) which command
we're doing. This should not be a huge problem for
aliases, which can simply use "--pager" or "--no-pager"
in the alias as appropriate.
For external commands, however, we don't know we even
have an external command until we exec it, and by then
it is too late to check the config.
An alternative approach would be to have a config mode
where we don't bother looking at .git/config, but only
at the user and system config files. This would make the
behavior consistent across builtins, aliases, and
external commands, at the cost of not allowing per-repo
pager config for at all.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-03 13:46:57 +02:00
|
|
|
use_pager = 0;
|
2007-08-19 19:24:36 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2009-10-12 22:30:32 +02:00
|
|
|
} else if (!strcmp(cmd, "--no-replace-objects")) {
|
2023-06-06 15:24:35 +02:00
|
|
|
disable_replace_refs();
|
2009-11-18 07:50:58 +01:00
|
|
|
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2006-07-25 20:24:22 +02:00
|
|
|
} else if (!strcmp(cmd, "--git-dir")) {
|
2006-12-22 14:56:25 +01:00
|
|
|
if (*argc < 2) {
|
2022-01-05 21:02:20 +01:00
|
|
|
fprintf(stderr, _("no directory given for '%s' option\n" ), "--git-dir");
|
2006-12-22 14:56:25 +01:00
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
2006-12-31 05:29:11 +01:00
|
|
|
setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
|
2007-06-08 22:57:55 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2006-07-25 20:24:22 +02:00
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
use skip_prefix to avoid magic numbers
It's a common idiom to match a prefix and then skip past it
with a magic number, like:
if (starts_with(foo, "bar"))
foo += 3;
This is easy to get wrong, since you have to count the
prefix string yourself, and there's no compiler check if the
string changes. We can use skip_prefix to avoid the magic
numbers here.
Note that some of these conversions could be much shorter.
For example:
if (starts_with(arg, "--foo=")) {
bar = arg + 6;
continue;
}
could become:
if (skip_prefix(arg, "--foo=", &bar))
continue;
However, I have left it as:
if (skip_prefix(arg, "--foo=", &v)) {
bar = v;
continue;
}
to visually match nearby cases which need to actually
process the string. Like:
if (skip_prefix(arg, "--foo=", &v)) {
bar = atoi(v);
continue;
}
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-18 21:47:50 +02:00
|
|
|
} else if (skip_prefix(cmd, "--git-dir=", &cmd)) {
|
|
|
|
setenv(GIT_DIR_ENVIRONMENT, cmd, 1);
|
2007-06-08 22:57:55 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 19:54:44 +02:00
|
|
|
} else if (!strcmp(cmd, "--namespace")) {
|
|
|
|
if (*argc < 2) {
|
2018-02-13 14:19:15 +01:00
|
|
|
fprintf(stderr, _("no namespace given for --namespace\n" ));
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 19:54:44 +02:00
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
|
|
|
setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
use skip_prefix to avoid magic numbers
It's a common idiom to match a prefix and then skip past it
with a magic number, like:
if (starts_with(foo, "bar"))
foo += 3;
This is easy to get wrong, since you have to count the
prefix string yourself, and there's no compiler check if the
string changes. We can use skip_prefix to avoid the magic
numbers here.
Note that some of these conversions could be much shorter.
For example:
if (starts_with(arg, "--foo=")) {
bar = arg + 6;
continue;
}
could become:
if (skip_prefix(arg, "--foo=", &bar))
continue;
However, I have left it as:
if (skip_prefix(arg, "--foo=", &v)) {
bar = v;
continue;
}
to visually match nearby cases which need to actually
process the string. Like:
if (skip_prefix(arg, "--foo=", &v)) {
bar = atoi(v);
continue;
}
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-18 21:47:50 +02:00
|
|
|
} else if (skip_prefix(cmd, "--namespace=", &cmd)) {
|
|
|
|
setenv(GIT_NAMESPACE_ENVIRONMENT, cmd, 1);
|
ref namespaces: infrastructure
Add support for dividing the refs of a single repository into multiple
namespaces, each of which can have its own branches, tags, and HEAD.
Git can expose each namespace as an independent repository to pull from
and push to, while sharing the object store, and exposing all the refs
to operations such as git-gc.
Storing multiple repositories as namespaces of a single repository
avoids storing duplicate copies of the same objects, such as when
storing multiple branches of the same source. The alternates mechanism
provides similar support for avoiding duplicates, but alternates do not
prevent duplication between new objects added to the repositories
without ongoing maintenance, while namespaces do.
To specify a namespace, set the GIT_NAMESPACE environment variable to
the namespace. For each ref namespace, git stores the corresponding
refs in a directory under refs/namespaces/. For example,
GIT_NAMESPACE=foo will store refs under refs/namespaces/foo/. You can
also specify namespaces via the --namespace option to git.
Note that namespaces which include a / will expand to a hierarchy of
namespaces; for example, GIT_NAMESPACE=foo/bar will store refs under
refs/namespaces/foo/refs/namespaces/bar/. This makes paths in
GIT_NAMESPACE behave hierarchically, so that cloning with
GIT_NAMESPACE=foo/bar produces the same result as cloning with
GIT_NAMESPACE=foo and cloning from that repo with GIT_NAMESPACE=bar. It
also avoids ambiguity with strange namespace paths such as
foo/refs/heads/, which could otherwise generate directory/file conflicts
within the refs directory.
Add the infrastructure for ref namespaces: handle the GIT_NAMESPACE
environment variable and --namespace option, and support iterating over
refs in a namespace.
Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Jamey Sharp <jamey@minilop.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-07-05 19:54:44 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2007-06-06 09:10:42 +02:00
|
|
|
} else if (!strcmp(cmd, "--work-tree")) {
|
|
|
|
if (*argc < 2) {
|
2022-01-05 21:02:20 +01:00
|
|
|
fprintf(stderr, _("no directory given for '%s' option\n" ), "--work-tree");
|
2007-06-06 09:10:42 +02:00
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
|
|
|
setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
|
2007-06-08 22:57:55 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2007-06-06 09:10:42 +02:00
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
use skip_prefix to avoid magic numbers
It's a common idiom to match a prefix and then skip past it
with a magic number, like:
if (starts_with(foo, "bar"))
foo += 3;
This is easy to get wrong, since you have to count the
prefix string yourself, and there's no compiler check if the
string changes. We can use skip_prefix to avoid the magic
numbers here.
Note that some of these conversions could be much shorter.
For example:
if (starts_with(arg, "--foo=")) {
bar = arg + 6;
continue;
}
could become:
if (skip_prefix(arg, "--foo=", &bar))
continue;
However, I have left it as:
if (skip_prefix(arg, "--foo=", &v)) {
bar = v;
continue;
}
to visually match nearby cases which need to actually
process the string. Like:
if (skip_prefix(arg, "--foo=", &v)) {
bar = atoi(v);
continue;
}
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-18 21:47:50 +02:00
|
|
|
} else if (skip_prefix(cmd, "--work-tree=", &cmd)) {
|
|
|
|
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
|
2007-06-08 22:57:55 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2006-07-25 20:24:22 +02:00
|
|
|
} else if (!strcmp(cmd, "--bare")) {
|
2014-07-28 20:31:57 +02:00
|
|
|
char *cwd = xgetcwd();
|
2007-08-27 09:58:06 +02:00
|
|
|
is_bare_repository_cfg = 1;
|
2014-07-28 20:31:57 +02:00
|
|
|
setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
|
|
|
|
free(cwd);
|
setup: suppress implicit "." work-tree for bare repos
If an explicit GIT_DIR is given without a working tree, we
implicitly assume that the current working directory should
be used as the working tree. E.g.,:
GIT_DIR=/some/repo.git git status
would compare against the cwd.
Unfortunately, we fool this rule for sub-invocations of git
by setting GIT_DIR internally ourselves. For example:
git init foo
cd foo/.git
git status ;# fails, as we expect
git config alias.st status
git status ;# does not fail, but should
What happens is that we run setup_git_directory when doing
alias lookup (since we need to see the config), set GIT_DIR
as a result, and then leave GIT_WORK_TREE blank (because we
do not have one). Then when we actually run the status
command, we do setup_git_directory again, which sees our
explicit GIT_DIR and uses the cwd as an implicit worktree.
It's tempting to argue that we should be suppressing that
second invocation of setup_git_directory, as it could use
the values we already found in memory. However, the problem
still exists for sub-processes (e.g., if "git status" were
an external command).
You can see another example with the "--bare" option, which
sets GIT_DIR explicitly. For example:
git init foo
cd foo/.git
git status ;# fails
git --bare status ;# does NOT fail
We need some way of telling sub-processes "even though
GIT_DIR is set, do not use cwd as an implicit working tree".
We could do it by putting a special token into
GIT_WORK_TREE, but the obvious choice (an empty string) has
some portability problems.
Instead, we add a new boolean variable, GIT_IMPLICIT_WORK_TREE,
which suppresses the use of cwd as a working tree when
GIT_DIR is set. We trigger the new variable when we know we
are in a bare setting.
The variable is left intentionally undocumented, as this is
an internal detail (for now, anyway). If somebody comes up
with a good alternate use for it, and once we are confident
we have shaken any bugs out of it, we can consider promoting
it further.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-08 10:32:22 +01:00
|
|
|
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
|
2007-06-08 22:57:55 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2010-03-26 23:53:57 +01:00
|
|
|
} else if (!strcmp(cmd, "-c")) {
|
|
|
|
if (*argc < 2) {
|
2018-02-13 14:19:15 +01:00
|
|
|
fprintf(stderr, _("-c expects a configuration string\n" ));
|
2010-03-26 23:53:57 +01:00
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
2010-08-23 21:16:00 +02:00
|
|
|
git_config_push_parameter((*argv)[1]);
|
2010-03-26 23:53:57 +01:00
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2021-04-29 14:55:34 +02:00
|
|
|
} else if (!strcmp(cmd, "--config-env")) {
|
|
|
|
if (*argc < 2) {
|
|
|
|
fprintf(stderr, _("no config key given for --config-env\n" ));
|
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
|
|
|
git_config_push_env((*argv)[1]);
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2021-01-12 13:26:45 +01:00
|
|
|
} else if (skip_prefix(cmd, "--config-env=", &cmd)) {
|
|
|
|
git_config_push_env(cmd);
|
add global --literal-pathspecs option
Git takes pathspec arguments in many places to limit the
scope of an operation. These pathspecs are treated not as
literal paths, but as glob patterns that can be fed to
fnmatch. When a user is giving a specific pattern, this is a
nice feature.
However, when programatically providing pathspecs, it can be
a nuisance. For example, to find the latest revision which
modified "$foo", one can use "git rev-list -- $foo". But if
"$foo" contains glob characters (e.g., "f*"), it will
erroneously match more entries than desired. The caller
needs to quote the characters in $foo, and even then, the
results may not be exactly the same as with a literal
pathspec. For instance, the depth checks in
match_pathspec_depth do not kick in if we match via fnmatch.
This patch introduces a global command-line option (i.e.,
one for "git" itself, not for specific commands) to turn
this behavior off. It also has a matching environment
variable, which can make it easier if you are a script or
porcelain interface that is going to issue many such
commands.
This option cannot turn off globbing for particular
pathspecs. That could eventually be done with a ":(noglob)"
magic pathspec prefix. However, that level of granularity is
more cumbersome to use for many cases, and doing ":(noglob)"
right would mean converting the whole codebase to use
"struct pathspec", as the usual "const char **pathspec"
cannot represent extra per-item flags.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 23:37:30 +01:00
|
|
|
} else if (!strcmp(cmd, "--literal-pathspecs")) {
|
|
|
|
setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "1", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
} else if (!strcmp(cmd, "--no-literal-pathspecs")) {
|
|
|
|
setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2013-07-14 10:36:08 +02:00
|
|
|
} else if (!strcmp(cmd, "--glob-pathspecs")) {
|
|
|
|
setenv(GIT_GLOB_PATHSPECS_ENVIRONMENT, "1", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
} else if (!strcmp(cmd, "--noglob-pathspecs")) {
|
|
|
|
setenv(GIT_NOGLOB_PATHSPECS_ENVIRONMENT, "1", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2013-07-14 10:36:09 +02:00
|
|
|
} else if (!strcmp(cmd, "--icase-pathspecs")) {
|
|
|
|
setenv(GIT_ICASE_PATHSPECS_ENVIRONMENT, "1", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
git: add --no-optional-locks option
Some tools like IDEs or fancy editors may periodically run
commands like "git status" in the background to keep track
of the state of the repository. Some of these commands may
refresh the index and write out the result in an
opportunistic way: if they can get the index lock, then they
update the on-disk index with any updates they find. And if
not, then their in-core refresh is lost and just has to be
recomputed by the next caller.
But taking the index lock may conflict with other operations
in the repository. Especially ones that the user is doing
themselves, which _aren't_ opportunistic. In other words,
"git status" knows how to back off when somebody else is
holding the lock, but other commands don't know that status
would be happy to drop the lock if somebody else wanted it.
There are a couple possible solutions:
1. Have some kind of "pseudo-lock" that allows other
commands to tell status that they want the lock.
This is likely to be complicated and error-prone to
implement (and maybe even impossible with just
dotlocks to work from, as it requires some
inter-process communication).
2. Avoid background runs of commands like "git status"
that want to do opportunistic updates, preferring
instead plumbing like diff-files, etc.
This is awkward for a couple of reasons. One is that
"status --porcelain" reports a lot more about the
repository state than is available from individual
plumbing commands. And two is that we actually _do_
want to see the refreshed index. We just don't want to
take a lock or write out the result. Whereas commands
like diff-files expect us to refresh the index
separately and write it to disk so that they can depend
on the result. But that write is exactly what we're
trying to avoid.
3. Ask "status" not to lock or write the index.
This is easy to implement. The big downside is that any
work done in refreshing the index for such a call is
lost when the process exits. So a background process
may end up re-hashing a changed file multiple times
until the user runs a command that does an index
refresh themselves.
This patch implements the option 3. The idea (and the test)
is largely stolen from a Git for Windows patch by Johannes
Schindelin, 67e5ce7f63 (status: offer *not* to lock the
index and update it, 2016-08-12). The twist here is that
instead of making this an option to "git status", it becomes
a "git" option and matching environment variable.
The reason there is two-fold:
1. An environment variable is carried through to
sub-processes. And whether an invocation is a
background process or not should apply to the whole
process tree. So you could do "git --no-optional-locks
foo", and if "foo" is a script or alias that calls
"status", you'll still get the effect.
2. There may be other programs that want the same
treatment.
I've punted here on finding more callers to convert,
since "status" is the obvious one to call as a repeated
background job. But "git diff"'s opportunistic refresh
of the index may be a good candidate.
The test is taken from 67e5ce7f63, and it's worth repeating
Johannes's explanation:
Note that the regression test added in this commit does
not *really* verify that no index.lock file was written;
that test is not possible in a portable way. Instead, we
verify that .git/index is rewritten *only* when `git
status` is run without `--no-optional-locks`.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-09-27 08:54:30 +02:00
|
|
|
} else if (!strcmp(cmd, "--no-optional-locks")) {
|
|
|
|
setenv(GIT_OPTIONAL_LOCKS_ENVIRONMENT, "0", 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2013-05-26 03:16:15 +02:00
|
|
|
} else if (!strcmp(cmd, "--shallow-file")) {
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2018-05-18 00:51:43 +02:00
|
|
|
set_alternate_shallow_file(the_repository, (*argv)[0], 1);
|
2013-05-26 03:16:15 +02:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2013-09-09 15:47:43 +02:00
|
|
|
} else if (!strcmp(cmd, "-C")) {
|
|
|
|
if (*argc < 2) {
|
2022-01-05 21:02:20 +01:00
|
|
|
fprintf(stderr, _("no directory given for '%s' option\n" ), "-C");
|
2013-09-09 15:47:43 +02:00
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
2015-03-06 12:18:08 +01:00
|
|
|
if ((*argv)[1][0]) {
|
|
|
|
if (chdir((*argv)[1]))
|
2018-02-13 14:19:15 +01:00
|
|
|
die_errno("cannot change to '%s'", (*argv)[1]);
|
2015-03-06 12:18:08 +01:00
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
}
|
2013-09-09 15:47:43 +02:00
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
2018-05-20 20:39:57 +02:00
|
|
|
} else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_query_");
|
2018-05-20 20:39:57 +02:00
|
|
|
if (!strcmp(cmd, "parseopt")) {
|
2018-05-20 20:39:58 +02:00
|
|
|
struct string_list list = STRING_LIST_INIT_DUP;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
list_builtins(&list, NO_PARSEOPT);
|
|
|
|
for (i = 0; i < list.nr; i++)
|
|
|
|
printf("%s ", list.items[i].string);
|
|
|
|
string_list_clear(&list, 0);
|
2018-05-20 20:39:57 +02:00
|
|
|
exit(0);
|
|
|
|
} else {
|
|
|
|
exit(list_cmds(cmd));
|
|
|
|
}
|
2023-05-06 06:15:29 +02:00
|
|
|
} else if (!strcmp(cmd, "--attr-source")) {
|
|
|
|
if (*argc < 2) {
|
|
|
|
fprintf(stderr, _("no attribute source given for --attr-source\n" ));
|
|
|
|
usage(git_usage_string);
|
|
|
|
}
|
|
|
|
setenv(GIT_ATTR_SOURCE_ENVIRONMENT, (*argv)[1], 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
|
|
|
} else if (skip_prefix(cmd, "--attr-source=", &cmd)) {
|
|
|
|
set_git_attr_source(cmd);
|
|
|
|
setenv(GIT_ATTR_SOURCE_ENVIRONMENT, cmd, 1);
|
|
|
|
if (envchanged)
|
|
|
|
*envchanged = 1;
|
2006-07-25 20:24:22 +02:00
|
|
|
} else {
|
2018-02-13 14:19:15 +01:00
|
|
|
fprintf(stderr, _("unknown option: %s\n"), cmd);
|
2006-07-30 23:42:25 +02:00
|
|
|
usage(git_usage_string);
|
2006-07-25 20:24:22 +02:00
|
|
|
}
|
2006-07-24 14:10:45 +02:00
|
|
|
|
|
|
|
(*argv)++;
|
|
|
|
(*argc)--;
|
|
|
|
}
|
2011-05-25 00:50:35 +02:00
|
|
|
return (*argv) - orig_argv;
|
2006-07-24 14:10:45 +02:00
|
|
|
}
|
|
|
|
|
2006-06-05 19:43:52 +02:00
|
|
|
static int handle_alias(int *argcp, const char ***argv)
|
|
|
|
{
|
2008-03-25 22:06:26 +01:00
|
|
|
int envchanged = 0, ret = 0, saved_errno = errno;
|
2006-07-30 03:30:29 +02:00
|
|
|
int count, option_count;
|
2009-05-01 11:06:36 +02:00
|
|
|
const char **new_argv;
|
2008-02-24 23:17:14 +01:00
|
|
|
const char *alias_command;
|
|
|
|
char *alias_string;
|
2006-07-30 03:30:29 +02:00
|
|
|
|
|
|
|
alias_command = (*argv)[0];
|
2008-02-24 23:17:14 +01:00
|
|
|
alias_string = alias_lookup(alias_command);
|
2006-07-30 03:30:29 +02:00
|
|
|
if (alias_string) {
|
git.c: handle_alias: prepend alias info when first argument is -h
Most git commands respond to -h anywhere in the command line, or at
least as a first and lone argument, by printing the usage
information. For aliases, we can provide a little more information that
might be useful in interpreting/understanding the following output by
prepending a line telling that the command is an alias, and for what.
When one invokes a simple alias, such as "cp = cherry-pick"
with -h, this results in
$ git cp -h
'cp' is aliased to 'cherry-pick'
usage: git cherry-pick [<options>] <commit-ish>...
...
When the alias consists of more than one word, this provides the
additional benefit of informing the user which options are implicit in
using the alias, e.g. with "cp = cherry-pick -n":
$ git cp -h
'cp' is aliased to 'cherry-pick -n'
usage: git cherry-pick [<options>] <commit-ish>...
...
For shell commands, we cannot know how it responds to -h, but printing
this line to stderr should not hurt, and can help in figuring out what
is happening in a case like
$ git sc -h
'sc' is aliased to '!somecommand'
somecommand: invalid option '-h'
Suggested-by: Jeff King <peff@peff.net>
Signed-off-by: Rasmus Villemoes <rv@rasmusvillemoes.dk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-10-09 13:59:08 +02:00
|
|
|
if (*argcp > 1 && !strcmp((*argv)[1], "-h"))
|
|
|
|
fprintf_ln(stderr, _("'%s' is aliased to '%s'"),
|
|
|
|
alias_command, alias_string);
|
2007-02-11 01:33:58 +01:00
|
|
|
if (alias_string[0] == '!') {
|
2016-02-22 23:44:21 +01:00
|
|
|
struct child_process child = CHILD_PROCESS_INIT;
|
2017-06-14 13:36:00 +02:00
|
|
|
int nongit_ok;
|
|
|
|
|
|
|
|
/* Aliases expect GIT_PREFIX, GIT_DIR etc to be set */
|
|
|
|
setup_git_directory_gently(&nongit_ok);
|
2011-01-07 00:00:38 +01:00
|
|
|
|
2010-07-15 00:55:12 +02:00
|
|
|
commit_pager_choice();
|
2011-01-07 00:00:38 +01:00
|
|
|
|
2016-02-22 23:44:21 +01:00
|
|
|
child.use_shell = 1;
|
Wait for child on signal death for aliases to externals
When we are running an alias to an external command, we want to wait for
that process to exit even after receiving ^C which normally kills the
git process. This is useful when the process is ignoring SIGINT (which
e.g. pagers often do), and then we don't want it to be killed.
Having an alias which invokes a pager is probably not common, but it can
be useful e.g. if you have an alias to a git command which uses a
subshell as one of the arguments (in which case you have to use an
external command, not an alias to a builtin).
This patch is similar to the previous commit, but the previous commit
fixed this only for aliases to builtins, while this commit does the same
for aliases to external commands. In addition to waiting after clean
like the previous commit, this also enables cleaning the child (that was
already enabled for aliases to builtins before the previous commit),
because wait_after_clean relies on it. Lastly, while the previous commit
fixed a regression, I don't think this has ever worked properly.
Signed-off-by: Trygve Aaberge <trygveaa@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-07-07 14:17:15 +02:00
|
|
|
child.clean_on_exit = 1;
|
|
|
|
child.wait_after_clean = 1;
|
2019-02-22 23:25:01 +01:00
|
|
|
child.trace2_child_class = "shell_alias";
|
2020-07-28 22:24:53 +02:00
|
|
|
strvec_push(&child.args, alias_string + 1);
|
|
|
|
strvec_pushv(&child.args, (*argv) + 1);
|
2011-01-07 00:00:38 +01:00
|
|
|
|
2020-07-29 02:37:20 +02:00
|
|
|
trace2_cmd_alias(alias_command, child.args.v);
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_list_config();
|
2020-03-20 22:06:15 +01:00
|
|
|
trace2_cmd_list_env_vars();
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_name("_run_shell_alias_");
|
|
|
|
|
2016-02-22 23:44:21 +01:00
|
|
|
ret = run_command(&child);
|
2011-01-07 00:00:38 +01:00
|
|
|
if (ret >= 0) /* normal exit */
|
|
|
|
exit(ret);
|
|
|
|
|
2018-11-10 06:16:00 +01:00
|
|
|
die_errno(_("while expanding alias '%s': '%s'"),
|
|
|
|
alias_command, alias_string + 1);
|
2007-02-11 01:33:58 +01:00
|
|
|
}
|
2006-07-30 03:30:29 +02:00
|
|
|
count = split_cmdline(alias_string, &new_argv);
|
2008-09-22 17:06:41 +02:00
|
|
|
if (count < 0)
|
2018-11-10 06:16:00 +01:00
|
|
|
die(_("bad alias.%s string: %s"), alias_command,
|
2018-11-10 06:16:01 +01:00
|
|
|
_(split_cmdline_strerror(count)));
|
2007-06-08 22:57:55 +02:00
|
|
|
option_count = handle_options(&new_argv, &count, &envchanged);
|
|
|
|
if (envchanged)
|
2018-11-10 06:16:00 +01:00
|
|
|
die(_("alias '%s' changes environment variables.\n"
|
|
|
|
"You can use '!git' in the alias to do this"),
|
|
|
|
alias_command);
|
2019-09-19 22:48:30 +02:00
|
|
|
MOVE_ARRAY(new_argv - option_count, new_argv, count);
|
2006-07-30 03:30:29 +02:00
|
|
|
new_argv -= option_count;
|
|
|
|
|
|
|
|
if (count < 1)
|
2018-11-10 06:16:00 +01:00
|
|
|
die(_("empty alias for %s"), alias_command);
|
2006-07-30 03:30:29 +02:00
|
|
|
|
|
|
|
if (!strcmp(alias_command, new_argv[0]))
|
2018-11-10 06:16:00 +01:00
|
|
|
die(_("recursive alias: %s"), alias_command);
|
2006-07-30 03:30:29 +02:00
|
|
|
|
2007-12-03 05:51:50 +01:00
|
|
|
trace_argv_printf(new_argv,
|
2006-09-02 18:23:48 +02:00
|
|
|
"trace: alias expansion: %s =>",
|
|
|
|
alias_command);
|
2006-06-25 15:56:18 +02:00
|
|
|
|
2014-09-16 20:56:57 +02:00
|
|
|
REALLOC_ARRAY(new_argv, count + *argcp);
|
2006-07-30 03:30:29 +02:00
|
|
|
/* insert after command name */
|
2019-09-19 22:48:30 +02:00
|
|
|
COPY_ARRAY(new_argv + count, *argv + 1, *argcp);
|
2006-06-05 19:43:52 +02:00
|
|
|
|
2019-02-22 23:25:01 +01:00
|
|
|
trace2_cmd_alias(alias_command, new_argv);
|
|
|
|
trace2_cmd_list_config();
|
2020-03-20 22:06:15 +01:00
|
|
|
trace2_cmd_list_env_vars();
|
2019-02-22 23:25:01 +01:00
|
|
|
|
2006-07-30 03:30:29 +02:00
|
|
|
*argv = new_argv;
|
|
|
|
*argcp += count - 1;
|
2006-06-05 19:43:52 +02:00
|
|
|
|
2006-07-30 03:30:29 +02:00
|
|
|
ret = 1;
|
2006-06-05 19:43:52 +02:00
|
|
|
}
|
|
|
|
|
2006-06-28 12:45:27 +02:00
|
|
|
errno = saved_errno;
|
|
|
|
|
2006-06-05 19:43:52 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-01-28 08:33:53 +01:00
|
|
|
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
2007-06-24 19:10:40 +02:00
|
|
|
{
|
2009-11-09 16:05:01 +01:00
|
|
|
int status, help;
|
2007-06-24 19:29:33 +02:00
|
|
|
struct stat st;
|
2007-06-24 19:10:40 +02:00
|
|
|
const char *prefix;
|
2021-12-06 16:55:55 +01:00
|
|
|
int run_setup = (p->option & (RUN_SETUP | RUN_SETUP_GENTLY));
|
2007-06-24 19:10:40 +02:00
|
|
|
|
2009-11-09 16:05:01 +01:00
|
|
|
help = argc == 2 && !strcmp(argv[1], "-h");
|
2021-12-06 16:55:55 +01:00
|
|
|
if (help && (run_setup & RUN_SETUP))
|
|
|
|
/* demote to GENTLY to allow 'git cmd -h' outside repo */
|
|
|
|
run_setup = RUN_SETUP_GENTLY;
|
|
|
|
|
|
|
|
if (run_setup & RUN_SETUP) {
|
|
|
|
prefix = setup_git_directory();
|
|
|
|
} else if (run_setup & RUN_SETUP_GENTLY) {
|
|
|
|
int nongit_ok;
|
|
|
|
prefix = setup_git_directory_gently(&nongit_ok);
|
|
|
|
} else {
|
|
|
|
prefix = NULL;
|
2009-11-09 16:05:01 +01:00
|
|
|
}
|
built-ins: trust the "prefix" from run_builtin()
Change code in "builtin/grep.c" and "builtin/ls-tree.c" to trust the
"prefix" passed from "run_builtin()". The "prefix" we get from setup.c
is either going to be NULL or a string of length >0, never "".
So we can drop the "prefix && *prefix" checks added for
"builtin/grep.c" in 0d042fecf2f (git-grep: show pathnames relative to
the current directory, 2006-08-11), and for "builtin/ls-tree.c" in
a69dd585fca (ls-tree: chomp leading directories when run from a
subdirectory, 2005-12-23).
As seen in code in revision.c that was added in cd676a51367 (diff
--relative: output paths as relative to the current subdirectory,
2008-02-12) we already have existing code that does away with this
assertion.
This makes it easier to reason about a subsequent change to the
"prefix_length" code in grep.c in a subsequent commit, and since we're
going to the trouble of doing that let's leave behind an assert() to
promise this to any future callers.
For "builtin/grep.c" it would be painful to pass the "prefix" down the
callchain of:
cmd_grep -> grep_tree -> grep_submodule -> grep_cache -> grep_oid ->
grep_source_name
So for the code that needs it in grep_source_name() let's add a
"grep_prefix" variable similar to the existing "ls_tree_prefix".
While at it let's move the code in cmd_ls_tree() around so that we
assign to the "ls_tree_prefix" right after declaring the variables,
and stop assigning to "prefix". We only subsequently used that
variable later in the function after clobbering it. Let's just use our
own "grep_prefix" instead.
Let's also add an assert() in git.c, so that we'll make this promise
about the "prefix" to any current and future callers, as well as to
any readers of the code.
Code history:
* The strlen() in "grep.c" hasn't been used since 493b7a08d80 (grep:
accept relative paths outside current working directory, 2009-09-05).
When that code was added in 0d042fecf2f (git-grep: show pathnames
relative to the current directory, 2006-08-11) we used the length.
But since 493b7a08d80 we haven't used it for anything except a
boolean check that we could have done on the "prefix" member
itself.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-02-16 01:00:34 +01:00
|
|
|
assert(!prefix || *prefix);
|
2021-12-06 16:55:55 +01:00
|
|
|
precompose_argv_prefix(argc, argv, NULL);
|
|
|
|
if (use_pager == -1 && run_setup &&
|
|
|
|
!(p->option & DELAY_PAGER_CONFIG))
|
|
|
|
use_pager = check_pager_config(p->cmd);
|
|
|
|
if (use_pager == -1 && p->option & USE_PAGER)
|
|
|
|
use_pager = 1;
|
|
|
|
if (run_setup && startup_info->have_repository)
|
|
|
|
/* get_git_dir() may set up repo, avoid that */
|
2023-02-19 01:25:27 +01:00
|
|
|
trace_repo_setup();
|
Allow per-command pager config
There is great debate over whether some commands should set
up a pager automatically. This patch allows individuals to
set their own pager preferences for each command, overriding
the default. For example, to disable the pager for git
status:
git config pager.status false
If "--pager" or "--no-pager" is specified on the command
line, it takes precedence over the config option.
There are two caveats:
- you can turn on the pager for plumbing commands.
Combined with "core.pager = always", this will probably
break a lot of things. Don't do it.
- This only works for builtin commands. The reason is
somewhat complex:
Calling git_config before we do setup_git_directory
has bad side effects, because it wants to know where
the git_dir is to find ".git/config". Unfortunately,
we cannot call setup_git_directory indiscriminately,
because some builtins (like "init") break if we do.
For builtins, this is OK, since we can just wait until
after we call setup_git_directory. But for aliases, we
don't know until we expand (recursively) which command
we're doing. This should not be a huge problem for
aliases, which can simply use "--pager" or "--no-pager"
in the alias as appropriate.
For external commands, however, we don't know we even
have an external command until we exec it, and by then
it is too late to check the config.
An alternative approach would be to have a config mode
where we don't bother looking at .git/config, but only
at the user and system config files. This would make the
behavior consistent across builtins, aliases, and
external commands, at the cost of not allowing per-repo
pager config for at all.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-03 13:46:57 +02:00
|
|
|
commit_pager_choice();
|
|
|
|
|
2009-11-09 16:05:01 +01:00
|
|
|
if (!help && p->option & NEED_WORK_TREE)
|
2007-11-03 12:23:11 +01:00
|
|
|
setup_work_tree();
|
|
|
|
|
2007-12-03 05:51:50 +01:00
|
|
|
trace_argv_printf(argv, "trace: built-in: git");
|
2019-02-22 23:25:01 +01:00
|
|