* Re: [PATCH v5 4/8] t/helper/test-config: check argc before accessing argv
From: Eric Sunshine @ 2020-09-02 7:18 UTC (permalink / raw)
To: Matheus Tavares
Cc: Git List, Junio C Hamano, Derrick Stolee, Elijah Newren,
Jonathan Tan, Jonathan Nieder
In-Reply-To: <0750191342754bcca398c6fdad522616b0f3fbc3.1599026986.git.matheus.bernardino@usp.br>
On Wed, Sep 2, 2020 at 2:18 AM Matheus Tavares
<matheus.bernardino@usp.br> wrote:
> Check that we have the expected argc in 'configset_get_value' and
> 'configset_get_value_multi' before trying to access argv elements.
>
> Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
> ---
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> @@ -138,7 +138,7 @@ int cmd__config(int argc, const char **argv)
> - } else if (!strcmp(argv[1], "configset_get_value")) {
> + } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
> for (i = 3; i < argc; i++) {
> @@ -156,7 +156,7 @@ int cmd__config(int argc, const char **argv)
> printf("Value not found for \"%s\"\n", argv[2]);
This is certainly a bug fix since it was accessing argv[2] without
checking that that element was even present, but the more significant
outcome of this change is that it now correctly diagnoses when these
two commands are called with the wrong number of arguments (just like
all the other commands -- except "iterate" -- diagnose incorrect
number of arguments). It might make sense, therefore, for the commit
message to focus on that improvement and mention the out-of-bounds
array access fix as a side-effect. However, that itself is not worth a
re-roll.
^ permalink raw reply
* Re: [PATCH v5 2/8] t1308-config-set: avoid false positives when using test-config
From: Eric Sunshine @ 2020-09-02 6:57 UTC (permalink / raw)
To: Matheus Tavares
Cc: Git List, Junio C Hamano, Derrick Stolee, Elijah Newren,
Jonathan Tan, Jonathan Nieder
In-Reply-To: <f53782f14c5f53da5d5537b369a810a94f9ce184.1599026986.git.matheus.bernardino@usp.br>
On Wed, Sep 2, 2020 at 2:18 AM Matheus Tavares
<matheus.bernardino@usp.br> wrote:
> One test in t1308 expects test-config to fail with exit code 128 due to
> a parsing error in the config machinery. But test-config might also exit
> with 128 for any other reason that leads it to call die(). Therefore the
> test can potentially succeed for the wrong reason. To avoid false
> positives, let's check test-config's output, in addition to the exit
> code, and make sure that the cause of the error is the one we expect in
> this test.
>
> Moreover, the test was using the auxiliary function check_config which
> optionally takes a string to compare the test-config stdout against.
> Because this string is optional, there is a risk that future callers may
> also check only the exit code and not the output. To avoid that, make
> the string parameter of this function mandatory.
>
> Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
> ---
> diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
> @@ -14,10 +14,7 @@ check_config () {
> expect_code=0
> fi &&
> op=$1 key=$2 && shift && shift &&
> - if test $# != 0
> - then
> - printf "%s\n" "$@"
> - fi >expect &&
> + printf "%s\n" "$@" >expect &&
This change in behavior is quite subtle. With the original code,
"expect" will be entirely empty if no argument is provided, whereas
with the revised code, "expect" will contain a single newline. This
could be improved by making the argument genuinely mandatory as stated
in the commit message. Perhaps something like this:
if test $# -eq 0
then
BUG "check_config 'value' argument missing"
fi &&
printf "%s\n" "$@" >expect &&
> @@ -130,7 +127,8 @@ test_expect_success 'check line error when NULL string is queried' '
> test_expect_success 'find integer if value is non parse-able' '
> - check_config expect_code 128 get_int lamb.head
> + test_expect_code 128 test-tool config get_int lamb.head 2>result &&
> + test_i18ngrep "fatal: bad numeric config value '\'none\'' for '\'lamb.head\''" result
> '
The complex '\'quoting\'' magic leaves and re-enters the single-quote
context of the test body and makes it difficult to reason about. Since
this is a pattern argument to grep, a simpler alternative would be:
test_i18ngrep "fatal: bad numeric config value .none. for
.lamb.head." result
Aside from that, do I understand correctly that all other callers
which expect a non-zero exit code will find the error message on
stdout, but this case will find it on stderr? That makes one wonder
if, rather than dropping use of check_config() here, instead
check_config() should be enhanced to accept an additional option, such
as 'stderr' which causes it to check stderr rather than stdout
(similar to how 'expect_code' allows the caller to override the
expected exit code). But perhaps that would be overengineered if this
case is not expected to come up again as more callers are added in the
future?
^ permalink raw reply
* [PATCH v5 8/8] config: add setting to ignore sparsity patterns in some cmds
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
When sparse checkout is enabled, some users expect the output of certain
commands (such as grep, diff, and log) to be also restricted within the
sparsity patterns. This would allow them to effectively work only on the
subset of files in which they are interested; and allow some commands to
possibly perform better, by not considering uninteresting paths. For
this reason, we taught grep to honor the sparsity patterns, in the
previous patch. But, on the other hand, allowing grep and the other
commands mentioned to optionally ignore the patterns also make for some
interesting use cases. E.g. using grep to search for a function
documentation that resides outside the sparse checkout.
In any case, there is no current way for users to configure the behavior
they want for these commands. Aiming to provide this flexibility, let's
introduce the sparse.restrictCmds setting (and the analogous
--[no]-restrict-to-sparse-paths global option). The default value is
true. For now, grep is the only one affected by this setting, but the
goal is to have support for more commands, in the future.
Helped-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
Documentation/config.txt | 2 +
Documentation/config/grep.txt | 8 ++
Documentation/config/sparse.txt | 20 ++++
Documentation/git.txt | 4 +
Makefile | 1 +
builtin/grep.c | 13 ++-
contrib/completion/git-completion.bash | 2 +
git.c | 5 +
sparse-checkout.c | 18 ++++
sparse-checkout.h | 11 +++
t/t7817-grep-sparse-checkout.sh | 132 ++++++++++++++++++++++++-
t/t9902-completion.sh | 4 +-
12 files changed, 214 insertions(+), 6 deletions(-)
create mode 100644 Documentation/config/sparse.txt
create mode 100644 sparse-checkout.c
create mode 100644 sparse-checkout.h
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3042d80978..3b6e0901b8 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -438,6 +438,8 @@ include::config/sequencer.txt[]
include::config/showbranch.txt[]
+include::config/sparse.txt[]
+
include::config/splitindex.txt[]
include::config/ssh.txt[]
diff --git a/Documentation/config/grep.txt b/Documentation/config/grep.txt
index dd51db38e1..a3275ab4b7 100644
--- a/Documentation/config/grep.txt
+++ b/Documentation/config/grep.txt
@@ -28,3 +28,11 @@ grep.fullName::
grep.fallbackToNoIndex::
If set to true, fall back to git grep --no-index if git grep
is executed outside of a git repository. Defaults to false.
+
+ifdef::git-grep[]
+sparse.restrictCmds::
+ See base definition in linkgit:git-config[1]. grep honors
+ sparse.restrictCmds by limiting searches to the sparsity paths in three
+ cases: when searching the working tree, when searching the index with
+ --cached, and when searching a specified commit.
+endif::git-grep[]
diff --git a/Documentation/config/sparse.txt b/Documentation/config/sparse.txt
new file mode 100644
index 0000000000..494761526e
--- /dev/null
+++ b/Documentation/config/sparse.txt
@@ -0,0 +1,20 @@
+sparse.restrictCmds::
+ Only meaningful in conjunction with core.sparseCheckout. This option
+ extends sparse checkouts (which limit which paths are written to the
+ working tree), so that output and operations are also limited to the
+ sparsity paths where possible and implemented. The purpose of this
+ option is to (1) focus output for the user on the portion of the
+ repository that is of interest to them, and (2) enable potentially
+ dramatic performance improvements, especially in conjunction with
+ partial clones.
++
+When this option is true (default), some git commands may limit their behavior
+to the paths specified by the sparsity patterns, or to the intersection of
+those paths and any (like `*.c`) that the user might also specify on the
+command line. When false, the affected commands will work on full trees,
+ignoring the sparsity patterns. For now, only git-grep honors this setting.
++
+Note: commands which export, integrity check, or create history will always
+operate on full trees (e.g. fast-export, format-patch, fsck, commit, etc.),
+unaffected by any sparsity patterns. Also, writing commands such as
+sparse-checkout and read-tree will not be affected by this configuration.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 2fc92586b5..d857509573 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -180,6 +180,10 @@ If you just want to run git as if it was started in `<path>` then use
Do not perform optional operations that require locks. This is
equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`.
+--[no-]restrict-to-sparse-paths::
+ Overrides the sparse.restrictCmds configuration (see
+ linkgit:git-config[1]) for this execution.
+
--list-cmds=group[,group...]::
List commands by group. This is an internal/experimental
option and may change or be removed in the future. Supported
diff --git a/Makefile b/Makefile
index 65f8cfb236..778c9e499e 100644
--- a/Makefile
+++ b/Makefile
@@ -982,6 +982,7 @@ LIB_OBJS += sha1-name.o
LIB_OBJS += shallow.o
LIB_OBJS += sideband.o
LIB_OBJS += sigchain.o
+LIB_OBJS += sparse-checkout.o
LIB_OBJS += split-index.o
LIB_OBJS += stable-qsort.o
LIB_OBJS += strbuf.o
diff --git a/builtin/grep.c b/builtin/grep.c
index a32815de0a..3fa364e91c 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -25,6 +25,7 @@
#include "submodule-config.h"
#include "object-store.h"
#include "packfile.h"
+#include "sparse-checkout.h"
static char const * const grep_usage[] = {
N_("git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"),
@@ -498,6 +499,7 @@ static int grep_cache(struct grep_opt *opt,
int nr;
struct strbuf name = STRBUF_INIT;
int name_base_len = 0;
+ int sparse_paths_only = restrict_to_sparse_paths(repo);
if (repo->submodule_prefix) {
name_base_len = strlen(repo->submodule_prefix);
strbuf_addstr(&name, repo->submodule_prefix);
@@ -509,7 +511,7 @@ static int grep_cache(struct grep_opt *opt,
for (nr = 0; nr < repo->index->cache_nr; nr++) {
const struct cache_entry *ce = repo->index->cache[nr];
- if (ce_skip_worktree(ce))
+ if (sparse_paths_only && ce_skip_worktree(ce))
continue;
strbuf_setlen(&name, name_base_len);
@@ -715,9 +717,10 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
int is_root_tree)
{
struct pattern_list *patterns = NULL;
+ int sparse_paths_only = restrict_to_sparse_paths(opt->repo);
int ret;
- if (is_root_tree)
+ if (is_root_tree && sparse_paths_only)
patterns = get_sparsity_patterns(opt->repo);
ret = do_grep_tree(opt, pathspec, tree, base, tn_len, is_root_tree,
@@ -1258,6 +1261,12 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (!use_index || untracked) {
int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
+
+ if (opt_restrict_to_sparse_paths >= 0) {
+ die(_("--[no-]restrict-to-sparse-paths is incompatible"
+ " with --no-index and --untracked"));
+ }
+
hit = grep_directory(&opt, &pathspec, use_exclude, use_index);
} else if (0 <= opt_exclude) {
die(_("--[no-]exclude-standard cannot be used for tracked contents"));
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9147fba3d5..de12766a70 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3402,6 +3402,8 @@ __git_main ()
--namespace=
--no-replace-objects
--help
+ --restrict-to-sparse-paths
+ --no-restrict-to-sparse-paths
"
;;
*)
diff --git a/git.c b/git.c
index 8bd1d7551d..81206b424c 100644
--- a/git.c
+++ b/git.c
@@ -5,6 +5,7 @@
#include "run-command.h"
#include "alias.h"
#include "shallow.h"
+#include "sparse-checkout.h"
#define RUN_SETUP (1<<0)
#define RUN_SETUP_GENTLY (1<<1)
@@ -311,6 +312,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
} else {
exit(list_cmds(cmd));
}
+ } else if (!strcmp(cmd, "--restrict-to-sparse-paths")) {
+ opt_restrict_to_sparse_paths = 1;
+ } else if (!strcmp(cmd, "--no-restrict-to-sparse-paths")) {
+ opt_restrict_to_sparse_paths = 0;
} else {
fprintf(stderr, _("unknown option: %s\n"), cmd);
usage(git_usage_string);
diff --git a/sparse-checkout.c b/sparse-checkout.c
new file mode 100644
index 0000000000..96c5ed5446
--- /dev/null
+++ b/sparse-checkout.c
@@ -0,0 +1,18 @@
+#include "cache.h"
+#include "config.h"
+#include "sparse-checkout.h"
+
+int opt_restrict_to_sparse_paths = -1;
+
+int restrict_to_sparse_paths(struct repository *repo)
+{
+ int ret;
+
+ if (opt_restrict_to_sparse_paths >= 0)
+ return opt_restrict_to_sparse_paths;
+
+ if (repo_config_get_bool(repo, "sparse.restrictcmds", &ret))
+ ret = 1;
+
+ return ret;
+}
diff --git a/sparse-checkout.h b/sparse-checkout.h
new file mode 100644
index 0000000000..a4805e443a
--- /dev/null
+++ b/sparse-checkout.h
@@ -0,0 +1,11 @@
+#ifndef SPARSE_CHECKOUT_H
+#define SPARSE_CHECKOUT_H
+
+struct repository;
+
+extern int opt_restrict_to_sparse_paths;
+
+/* Whether or not cmds should restrict behavior on sparse paths, in this repo */
+int restrict_to_sparse_paths(struct repository *repo);
+
+#endif /* SPARSE_CHECKOUT_H */
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
index b3109e3479..f93a4f71d1 100755
--- a/t/t7817-grep-sparse-checkout.sh
+++ b/t/t7817-grep-sparse-checkout.sh
@@ -80,10 +80,10 @@ test_expect_success 'setup' '
test_path_is_file sub2/a
'
-# The test below checks a special case: the sparsity patterns exclude '/b'
+# The two tests below check a special case: the sparsity patterns exclude '/b'
# and sparse checkout is enabled, but the path exists in the working tree (e.g.
# manually created after `git sparse-checkout init`). In this case, grep should
-# skip it.
+# skip the file by default, but not with --no-restrict-to-sparse-paths.
test_expect_success 'grep in working tree should honor sparse checkout' '
cat >expect <<-EOF &&
a:text
@@ -93,6 +93,16 @@ test_expect_success 'grep in working tree should honor sparse checkout' '
git grep "text" >actual &&
test_cmp expect actual
'
+test_expect_success 'grep w/ --no-restrict-to-sparse-paths for sparsely excluded but present paths' '
+ cat >expect <<-EOF &&
+ a:text
+ b:new-text
+ EOF
+ echo "new-text" >b &&
+ test_when_finished "rm b" &&
+ git --no-restrict-to-sparse-paths grep "text" >actual &&
+ test_cmp expect actual
+'
test_expect_success 'grep unmerged file despite not matching sparsity patterns' '
cat >expect <<-EOF &&
@@ -157,7 +167,7 @@ test_expect_success 'grep <tree-ish> should ignore sparsity patterns' '
'
# Note that sub2/ is present in the worktree but it is excluded by the sparsity
-# patterns, so grep should not recurse into it.
+# patterns, so grep should only recurse into it with --no-restrict-to-sparse-paths.
test_expect_success 'grep --recurse-submodules should honor sparse checkout in submodule' '
cat >expect <<-EOF &&
a:text
@@ -166,6 +176,15 @@ test_expect_success 'grep --recurse-submodules should honor sparse checkout in s
git grep --recurse-submodules "text" >actual &&
test_cmp expect actual
'
+test_expect_success 'grep --recurse-submodules should search in excluded submodules w/ --no-restrict-to-sparse-paths' '
+ cat >expect <<-EOF &&
+ a:text
+ sub/B/b:text
+ sub2/a:text
+ EOF
+ git --no-restrict-to-sparse-paths grep --recurse-submodules "text" >actual &&
+ test_cmp expect actual
+'
test_expect_success 'grep --recurse-submodules --cached should honor sparse checkout in submodule' '
cat >expect <<-EOF &&
@@ -192,4 +211,111 @@ test_expect_success 'grep --recurse-submodules <commit-ish> should honor sparse
test_cmp expect_tag-to-commit actual_tag-to-commit
'
+for cmd in 'git --no-restrict-to-sparse-paths grep' \
+ 'git -c sparse.restrictCmds=false grep' \
+ 'git -c sparse.restrictCmds=true --no-restrict-to-sparse-paths grep'
+do
+
+ test_expect_success "$cmd --cached should ignore sparsity patterns" '
+ cat >expect <<-EOF &&
+ a:text
+ b:text
+ dir/c:text
+ EOF
+ $cmd --cached "text" >actual &&
+ test_cmp expect actual
+ '
+
+ test_expect_success "$cmd <commit-ish> should ignore sparsity patterns" '
+ commit=$(git rev-parse HEAD) &&
+ cat >expect_commit <<-EOF &&
+ $commit:a:text
+ $commit:b:text
+ $commit:dir/c:text
+ EOF
+ cat >expect_tag-to-commit <<-EOF &&
+ tag-to-commit:a:text
+ tag-to-commit:b:text
+ tag-to-commit:dir/c:text
+ EOF
+ $cmd "text" $commit >actual_commit &&
+ test_cmp expect_commit actual_commit &&
+ $cmd "text" tag-to-commit >actual_tag-to-commit &&
+ test_cmp expect_tag-to-commit actual_tag-to-commit
+ '
+done
+
+test_expect_success 'grep --recurse-submodules --cached w/ --no-restrict-to-sparse-paths' '
+ cat >expect <<-EOF &&
+ a:text
+ b:text
+ dir/c:text
+ sub/A/a:text
+ sub/B/b:text
+ sub2/a:text
+ EOF
+ git --no-restrict-to-sparse-paths grep --recurse-submodules --cached \
+ "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules <commit-ish> w/ --no-restrict-to-sparse-paths' '
+ commit=$(git rev-parse HEAD) &&
+ cat >expect_commit <<-EOF &&
+ $commit:a:text
+ $commit:b:text
+ $commit:dir/c:text
+ $commit:sub/A/a:text
+ $commit:sub/B/b:text
+ $commit:sub2/a:text
+ EOF
+ cat >expect_tag-to-commit <<-EOF &&
+ tag-to-commit:a:text
+ tag-to-commit:b:text
+ tag-to-commit:dir/c:text
+ tag-to-commit:sub/A/a:text
+ tag-to-commit:sub/B/b:text
+ tag-to-commit:sub2/a:text
+ EOF
+ git --no-restrict-to-sparse-paths grep --recurse-submodules "text" \
+ $commit >actual_commit &&
+ test_cmp expect_commit actual_commit &&
+ git --no-restrict-to-sparse-paths grep --recurse-submodules "text" \
+ tag-to-commit >actual_tag-to-commit &&
+ test_cmp expect_tag-to-commit actual_tag-to-commit
+'
+
+test_expect_success 'should respect the sparse.restrictCmds values from submodules' '
+ cat >expect <<-EOF &&
+ a:text
+ sub/A/a:text
+ sub/B/b:text
+ EOF
+ test_config -C sub sparse.restrictCmds false &&
+ git grep --cached --recurse-submodules "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'should propagate --[no]-restrict-to-sparse-paths to submodules' '
+ cat >expect <<-EOF &&
+ a:text
+ b:text
+ dir/c:text
+ sub/A/a:text
+ sub/B/b:text
+ sub2/a:text
+ EOF
+ test_config -C sub sparse.restrictCmds true &&
+ git --no-restrict-to-sparse-paths grep --cached --recurse-submodules "text" >actual &&
+ test_cmp expect actual
+'
+
+for opt in '--untracked' '--no-index'
+do
+ test_expect_success "--[no]-restrict-to-sparse-paths and $opt are incompatible" "
+ test_must_fail git --restrict-to-sparse-paths grep $opt . 2>actual &&
+ test_i18ngrep 'restrict-to-sparse-paths is incompatible with' actual
+ "
+done
+
test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 8425b9a531..a8c2ac9d70 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1928,6 +1928,8 @@ test_expect_success 'double dash "git" itself' '
--namespace=
--no-replace-objects Z
--help Z
+ --restrict-to-sparse-paths Z
+ --no-restrict-to-sparse-paths Z
EOF
'
@@ -1970,7 +1972,7 @@ test_expect_success 'general options' '
test_completion "git --nam" "--namespace=" &&
test_completion "git --bar" "--bare " &&
test_completion "git --inf" "--info-path " &&
- test_completion "git --no-r" "--no-replace-objects "
+ test_completion "git --no-rep" "--no-replace-objects "
'
test_expect_success 'general options plus command' '
--
2.28.0
^ permalink raw reply related
* [PATCH v5 7/8] grep: honor sparse checkout patterns
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
One of the main uses for a sparse checkout is to allow users to focus on
the subset of files in a repository in which they are interested. But
git-grep currently ignores the sparsity patterns and reports all matches
found outside this subset, which kind of goes in the opposite direction.
There are some use cases for ignoring the sparsity patterns and the next
commit will add an option to obtain this behavior, but here we start by
making grep honor the sparsity boundaries in every case where this is
relevant:
- git grep in worktree
- git grep --cached
- git grep $REVISION
For the worktree and cached cases, we iterate over paths without the
SKIP_WORKTREE bit set, and limit our searches to these paths. For the
$REVISION case, we limit the paths we search to those that match the
sparsity patterns. (We do not check the SKIP_WORKTREE bit for the
$REVISION case, because $REVISION may contain paths that do not exist in
HEAD and thus for which we have no SKIP_WORKTREE bit to consult. The
sparsity patterns tell us how the SKIP_WORKTREE bit would be set if we
were to check out $REVISION, so we consult those. Also, we don't use the
sparsity patterns with the worktree or cached cases, both because we
have a bit we can check directly and more efficiently, and because
unmerged entries from a merge or a rebase could cause more files to
temporarily be present than the sparsity patterns would normally
select.)
Note that there is a special case here: `git grep $TREE`. In this case,
we cannot know whether $TREE corresponds to the root of the repository
or some sub-tree, and thus there is no way for us to know which sparsity
patterns, if any, apply. So the $TREE case will not use sparsity
patterns or any SKIP_WORKTREE bits and will instead always search all
files within the $TREE.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
builtin/grep.c | 125 ++++++++++++++++++--
t/t7011-skip-worktree-reading.sh | 9 --
t/t7817-grep-sparse-checkout.sh | 195 +++++++++++++++++++++++++++++++
3 files changed, 312 insertions(+), 17 deletions(-)
create mode 100755 t/t7817-grep-sparse-checkout.sh
diff --git a/builtin/grep.c b/builtin/grep.c
index f58979bc3f..a32815de0a 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -410,7 +410,7 @@ static int grep_cache(struct grep_opt *opt,
const struct pathspec *pathspec, int cached);
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
struct tree_desc *tree, struct strbuf *base, int tn_len,
- int check_attr);
+ int is_root_tree);
static int grep_submodule(struct grep_opt *opt,
const struct pathspec *pathspec,
@@ -508,6 +508,10 @@ static int grep_cache(struct grep_opt *opt,
for (nr = 0; nr < repo->index->cache_nr; nr++) {
const struct cache_entry *ce = repo->index->cache[nr];
+
+ if (ce_skip_worktree(ce))
+ continue;
+
strbuf_setlen(&name, name_base_len);
strbuf_addstr(&name, ce->name);
@@ -520,8 +524,7 @@ static int grep_cache(struct grep_opt *opt,
* cache entry are identical, even if worktree file has
* been modified, so use cache version instead
*/
- if (cached || (ce->ce_flags & CE_VALID) ||
- ce_skip_worktree(ce)) {
+ if (cached || (ce->ce_flags & CE_VALID)) {
if (ce_stage(ce) || ce_intent_to_add(ce))
continue;
hit |= grep_oid(opt, &ce->oid, name.buf,
@@ -552,9 +555,76 @@ static int grep_cache(struct grep_opt *opt,
return hit;
}
-static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
- struct tree_desc *tree, struct strbuf *base, int tn_len,
- int check_attr)
+static struct pattern_list *get_sparsity_patterns(struct repository *repo)
+{
+ struct pattern_list *patterns;
+ char *sparse_file;
+ int sparse_config, cone_config;
+
+ if (repo_config_get_bool(repo, "core.sparsecheckout", &sparse_config) ||
+ !sparse_config) {
+ return NULL;
+ }
+
+ sparse_file = repo_git_path(repo, "info/sparse-checkout");
+ patterns = xcalloc(1, sizeof(*patterns));
+
+ if (repo_config_get_bool(repo, "core.sparsecheckoutcone", &cone_config))
+ cone_config = 0;
+ patterns->use_cone_patterns = cone_config;
+
+ if (add_patterns_from_file_to_list(sparse_file, "", 0, patterns, NULL)) {
+ if (file_exists(sparse_file)) {
+ warning(_("failed to load sparse-checkout file: '%s'"),
+ sparse_file);
+ }
+ free(sparse_file);
+ free(patterns);
+ return NULL;
+ }
+
+ free(sparse_file);
+ return patterns;
+}
+
+static int path_in_sparse_checkout(struct strbuf *path, int prefix_len,
+ unsigned int entry_mode,
+ struct index_state *istate,
+ struct pattern_list *sparsity,
+ enum pattern_match_result parent_match,
+ enum pattern_match_result *match)
+{
+ int dtype = DT_UNKNOWN;
+ int is_dir = S_ISDIR(entry_mode);
+
+ if (parent_match == MATCHED_RECURSIVE) {
+ *match = parent_match;
+ return 1;
+ }
+
+ if (is_dir && !is_dir_sep(path->buf[path->len - 1]))
+ strbuf_addch(path, '/');
+
+ *match = path_matches_pattern_list(path->buf, path->len,
+ path->buf + prefix_len, &dtype,
+ sparsity, istate);
+ if (*match == UNDECIDED)
+ *match = parent_match;
+
+ if (is_dir)
+ strbuf_trim_trailing_dir_sep(path);
+
+ if (*match == NOT_MATCHED &&
+ (!is_dir || (is_dir && sparsity->use_cone_patterns)))
+ return 0;
+
+ return 1;
+}
+
+static int do_grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
+ struct tree_desc *tree, struct strbuf *base, int tn_len,
+ int check_attr, struct pattern_list *sparsity,
+ enum pattern_match_result default_sparsity_match)
{
struct repository *repo = opt->repo;
int hit = 0;
@@ -570,6 +640,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
while (tree_entry(tree, &entry)) {
int te_len = tree_entry_len(&entry);
+ enum pattern_match_result sparsity_match = 0;
if (match != all_entries_interesting) {
strbuf_addstr(&name, base->buf + tn_len);
@@ -586,6 +657,19 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
strbuf_add(base, entry.path, te_len);
+ if (sparsity) {
+ struct strbuf path = STRBUF_INIT;
+ strbuf_addstr(&path, base->buf + tn_len);
+
+ if (!path_in_sparse_checkout(&path, old_baselen - tn_len,
+ entry.mode, repo->index,
+ sparsity, default_sparsity_match,
+ &sparsity_match)) {
+ strbuf_setlen(base, old_baselen);
+ continue;
+ }
+ }
+
if (S_ISREG(entry.mode)) {
hit |= grep_oid(opt, &entry.oid, base->buf, tn_len,
check_attr ? base->buf + tn_len : NULL);
@@ -602,8 +686,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
strbuf_addch(base, '/');
init_tree_desc(&sub, data, size);
- hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
- check_attr);
+ hit |= do_grep_tree(opt, pathspec, &sub, base, tn_len,
+ check_attr, sparsity, sparsity_match);
free(data);
} else if (recurse_submodules && S_ISGITLINK(entry.mode)) {
hit |= grep_submodule(opt, pathspec, &entry.oid,
@@ -621,6 +705,31 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
return hit;
}
+/*
+ * Note: sparsity patterns and paths' attributes will only be considered if
+ * is_root_tree has true value. (Otherwise, we cannot properly perform pattern
+ * matching on paths.)
+ */
+static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
+ struct tree_desc *tree, struct strbuf *base, int tn_len,
+ int is_root_tree)
+{
+ struct pattern_list *patterns = NULL;
+ int ret;
+
+ if (is_root_tree)
+ patterns = get_sparsity_patterns(opt->repo);
+
+ ret = do_grep_tree(opt, pathspec, tree, base, tn_len, is_root_tree,
+ patterns, 0);
+
+ if (patterns) {
+ clear_pattern_list(patterns);
+ free(patterns);
+ }
+ return ret;
+}
+
static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
struct object *obj, const char *name, const char *path)
{
diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh
index 37525cae3a..26852586ac 100755
--- a/t/t7011-skip-worktree-reading.sh
+++ b/t/t7011-skip-worktree-reading.sh
@@ -109,15 +109,6 @@ test_expect_success 'ls-files --modified' '
test -z "$(git ls-files -m)"
'
-test_expect_success 'grep with skip-worktree file' '
- git update-index --no-skip-worktree 1 &&
- echo test > 1 &&
- git update-index 1 &&
- git update-index --skip-worktree 1 &&
- rm 1 &&
- test "$(git grep --no-ext-grep test)" = "1:test"
-'
-
echo ":000000 100644 $ZERO_OID $EMPTY_BLOB A 1" > expected
test_expect_success 'diff-index does not examine skip-worktree absent entries' '
setup_absent &&
diff --git a/t/t7817-grep-sparse-checkout.sh b/t/t7817-grep-sparse-checkout.sh
new file mode 100755
index 0000000000..b3109e3479
--- /dev/null
+++ b/t/t7817-grep-sparse-checkout.sh
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+test_description='grep in sparse checkout
+
+This test creates a repo with the following structure:
+
+.
+|-- a
+|-- b
+|-- dir
+| `-- c
+|-- sub
+| |-- A
+| | `-- a
+| `-- B
+| `-- b
+`-- sub2
+ `-- a
+
+Where the outer repository has non-cone mode sparsity patterns, sub is a
+submodule with cone mode sparsity patterns and sub2 is a submodule that is
+excluded by the superproject sparsity patterns. The resulting sparse checkout
+should leave the following structure in the working tree:
+
+.
+|-- a
+|-- sub
+| `-- B
+| `-- b
+`-- sub2
+ `-- a
+
+But note that sub2 should have the SKIP_WORKTREE bit set.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo "text" >a &&
+ echo "text" >b &&
+ mkdir dir &&
+ echo "text" >dir/c &&
+
+ git init sub &&
+ (
+ cd sub &&
+ mkdir A B &&
+ echo "text" >A/a &&
+ echo "text" >B/b &&
+ git add A B &&
+ git commit -m sub &&
+ git sparse-checkout init --cone &&
+ git sparse-checkout set B
+ ) &&
+
+ git init sub2 &&
+ (
+ cd sub2 &&
+ echo "text" >a &&
+ git add a &&
+ git commit -m sub2
+ ) &&
+
+ git submodule add ./sub &&
+ git submodule add ./sub2 &&
+ git add a b dir &&
+ git commit -m super &&
+ git sparse-checkout init --no-cone &&
+ git sparse-checkout set "/*" "!b" "!/*/" "sub" &&
+
+ git tag -am tag-to-commit tag-to-commit HEAD &&
+ tree=$(git rev-parse HEAD^{tree}) &&
+ git tag -am tag-to-tree tag-to-tree $tree &&
+
+ test_path_is_missing b &&
+ test_path_is_missing dir &&
+ test_path_is_missing sub/A &&
+ test_path_is_file a &&
+ test_path_is_file sub/B/b &&
+ test_path_is_file sub2/a
+'
+
+# The test below checks a special case: the sparsity patterns exclude '/b'
+# and sparse checkout is enabled, but the path exists in the working tree (e.g.
+# manually created after `git sparse-checkout init`). In this case, grep should
+# skip it.
+test_expect_success 'grep in working tree should honor sparse checkout' '
+ cat >expect <<-EOF &&
+ a:text
+ EOF
+ echo "new-text" >b &&
+ test_when_finished "rm b" &&
+ git grep "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep unmerged file despite not matching sparsity patterns' '
+ cat >expect <<-EOF &&
+ b:modified-b-in-branchX
+ b:modified-b-in-branchY
+ EOF
+ test_when_finished "test_might_fail git merge --abort && \
+ git checkout master" &&
+
+ git sparse-checkout disable &&
+ git checkout -b branchY master &&
+ test_commit modified-b-in-branchY b &&
+ git checkout -b branchX master &&
+ test_commit modified-b-in-branchX b &&
+
+ git sparse-checkout init &&
+ test_path_is_missing b &&
+ test_must_fail git merge branchY &&
+ git grep "modified-b" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep --cached should honor sparse checkout' '
+ cat >expect <<-EOF &&
+ a:text
+ EOF
+ git grep --cached "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep <commit-ish> should honor sparse checkout' '
+ commit=$(git rev-parse HEAD) &&
+ cat >expect_commit <<-EOF &&
+ $commit:a:text
+ EOF
+ cat >expect_tag-to-commit <<-EOF &&
+ tag-to-commit:a:text
+ EOF
+ git grep "text" $commit >actual_commit &&
+ test_cmp expect_commit actual_commit &&
+ git grep "text" tag-to-commit >actual_tag-to-commit &&
+ test_cmp expect_tag-to-commit actual_tag-to-commit
+'
+
+test_expect_success 'grep <tree-ish> should ignore sparsity patterns' '
+ commit=$(git rev-parse HEAD) &&
+ tree=$(git rev-parse HEAD^{tree}) &&
+ cat >expect_tree <<-EOF &&
+ $tree:a:text
+ $tree:b:text
+ $tree:dir/c:text
+ EOF
+ cat >expect_tag-to-tree <<-EOF &&
+ tag-to-tree:a:text
+ tag-to-tree:b:text
+ tag-to-tree:dir/c:text
+ EOF
+ git grep "text" $tree >actual_tree &&
+ test_cmp expect_tree actual_tree &&
+ git grep "text" tag-to-tree >actual_tag-to-tree &&
+ test_cmp expect_tag-to-tree actual_tag-to-tree
+'
+
+# Note that sub2/ is present in the worktree but it is excluded by the sparsity
+# patterns, so grep should not recurse into it.
+test_expect_success 'grep --recurse-submodules should honor sparse checkout in submodule' '
+ cat >expect <<-EOF &&
+ a:text
+ sub/B/b:text
+ EOF
+ git grep --recurse-submodules "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules --cached should honor sparse checkout in submodule' '
+ cat >expect <<-EOF &&
+ a:text
+ sub/B/b:text
+ EOF
+ git grep --recurse-submodules --cached "text" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'grep --recurse-submodules <commit-ish> should honor sparse checkout in submodule' '
+ commit=$(git rev-parse HEAD) &&
+ cat >expect_commit <<-EOF &&
+ $commit:a:text
+ $commit:sub/B/b:text
+ EOF
+ cat >expect_tag-to-commit <<-EOF &&
+ tag-to-commit:a:text
+ tag-to-commit:sub/B/b:text
+ EOF
+ git grep --recurse-submodules "text" $commit >actual_commit &&
+ test_cmp expect_commit actual_commit &&
+ git grep --recurse-submodules "text" tag-to-commit >actual_tag-to-commit &&
+ test_cmp expect_tag-to-commit actual_tag-to-commit
+'
+
+test_done
--
2.28.0
^ permalink raw reply related
* [PATCH v5 6/8] config: correctly read worktree configs in submodules
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
The config machinery is not able to read worktree configs from a
submodule in a process where the_repository represents the superproject.
Furthermore, when extensions.worktreeConfig is set on the superproject,
querying for a worktree config in a submodule will, instead, return
the value set at the superproject.
The problem resides in do_git_config_sequence(). Although the function
receives a git_dir string, it uses the_repository->git_dir when making
the path to the worktree config file. And when checking if
extensions.worktreeConfig is set, it uses the global
repository_format_worktree_config variable, which refers to
the_repository only. So let's fix this by using the git_dir given to the
function and reading the extension value from the right place. Also add
a test to avoid any regressions.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
config.c | 21 ++++++++++---
t/helper/test-config.c | 62 ++++++++++++++++++++++++++++++++------
t/t2404-worktree-config.sh | 16 ++++++++++
3 files changed, 85 insertions(+), 14 deletions(-)
diff --git a/config.c b/config.c
index 2bdff4457b..e1e7fab6dc 100644
--- a/config.c
+++ b/config.c
@@ -1747,11 +1747,22 @@ static int do_git_config_sequence(const struct config_options *opts,
ret += git_config_from_file(fn, repo_config, data);
current_parsing_scope = CONFIG_SCOPE_WORKTREE;
- if (!opts->ignore_worktree && repository_format_worktree_config) {
- char *path = git_pathdup("config.worktree");
- if (!access_or_die(path, R_OK, 0))
- ret += git_config_from_file(fn, path, data);
- free(path);
+ if (!opts->ignore_worktree && repo_config && opts->git_dir) {
+ struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
+ struct strbuf buf = STRBUF_INIT;
+
+ read_repository_format(&repo_fmt, repo_config);
+
+ if (!verify_repository_format(&repo_fmt, &buf) &&
+ repo_fmt.worktree_config) {
+ char *path = mkpathdup("%s/config.worktree", opts->git_dir);
+ if (!access_or_die(path, R_OK, 0))
+ ret += git_config_from_file(fn, path, data);
+ free(path);
+ }
+
+ strbuf_release(&buf);
+ clear_repository_format(&repo_fmt);
}
current_parsing_scope = CONFIG_SCOPE_COMMAND;
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 8fe43e9775..2924c09c21 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -2,12 +2,20 @@
#include "cache.h"
#include "config.h"
#include "string-list.h"
+#include "submodule-config.h"
+#include "parse-options.h"
/*
* This program exposes the C API of the configuration mechanism
* as a set of simple commands in order to facilitate testing.
*
- * Reads stdin and prints result of command to stdout:
+ * Usage: test-tool config [--submodule=<path>] <cmd> [<args>]
+ *
+ * If --submodule=<path> is given, <cmd> will operate on the submodule at the
+ * given <path>. This option is not valid for the commands: read_early_config,
+ * configset_get_value and configset_get_value_multi.
+ *
+ * Possible cmds are:
*
* get_value -> prints the value with highest priority for the entered key
*
@@ -72,14 +80,34 @@ static int early_config_cb(const char *var, const char *value, void *vdata)
#define TC_VALUE_NOT_FOUND 1
#define TC_CONFIG_FILE_ERROR 2
+static const char *test_config_usage[] = {
+ "test-tool config [--submodule=<path>] <cmd> [<args>]",
+ NULL
+};
+
int cmd__config(int argc, const char **argv)
{
int i, val, ret = 0;
const char *v;
const struct string_list *strptr;
struct config_set cs;
+ struct repository subrepo, *repo = the_repository;
+ const char *subrepo_path = NULL;
+
+ struct option options[] = {
+ OPT_STRING(0, "submodule", &subrepo_path, "path",
+ "run <cmd> on the submodule at <path>"),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, NULL, options, test_config_usage,
+ PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_STOP_AT_NON_OPTION);
+ if (argc < 2)
+ die("Please, provide a command name on the command-line");
if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
+ if (subrepo_path)
+ die("cannot use --submodule with read_early_config");
read_early_config(early_config_cb, (void *)argv[2]);
return ret;
}
@@ -88,11 +116,18 @@ int cmd__config(int argc, const char **argv)
git_configset_init(&cs);
- if (argc < 2)
- die("Please, provide a command name on the command-line");
+ if (subrepo_path) {
+ const struct submodule *sub;
+
+ sub = submodule_from_path(the_repository, &null_oid, subrepo_path);
+ if (!sub || repo_submodule_init(&subrepo, the_repository, sub))
+ die("invalid argument to --submodule: '%s'", subrepo_path);
+
+ repo = &subrepo;
+ }
if (argc == 3 && !strcmp(argv[1], "get_value")) {
- if (!git_config_get_value(argv[2], &v)) {
+ if (!repo_config_get_value(repo, argv[2], &v)) {
if (!v)
printf("(NULL)\n");
else
@@ -102,7 +137,7 @@ int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
- strptr = git_config_get_value_multi(argv[2]);
+ strptr = repo_config_get_value_multi(repo, argv[2]);
if (strptr) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
@@ -116,27 +151,31 @@ int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
- if (!git_config_get_int(argv[2], &val)) {
+ if (!repo_config_get_int(repo, argv[2], &val)) {
printf("%d\n", val);
} else {
printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
- if (!git_config_get_bool(argv[2], &val)) {
+ if (!repo_config_get_bool(repo, argv[2], &val)) {
printf("%d\n", val);
} else {
+
printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_string")) {
- if (!git_config_get_string_tmp(argv[2], &v)) {
+ if (!repo_config_get_string_tmp(repo, argv[2], &v)) {
printf("%s\n", v);
} else {
printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
+ if (subrepo_path)
+ die("cannot use --submodule with configset_get_value");
+
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ -155,6 +194,9 @@ int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
+ if (subrepo_path)
+ die("cannot use --submodule with configset_get_value_multi");
+
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ -177,12 +219,14 @@ int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
} else if (!strcmp(argv[1], "iterate")) {
- git_config(iterate_cb, NULL);
+ repo_config(repo, iterate_cb, NULL);
} else {
die("%s: Please check the syntax and the function name", argv[0]);
}
out:
git_configset_clear(&cs);
+ if (repo != the_repository)
+ repo_clear(repo);
return ret;
}
diff --git a/t/t2404-worktree-config.sh b/t/t2404-worktree-config.sh
index 9536d10919..1e32c93735 100755
--- a/t/t2404-worktree-config.sh
+++ b/t/t2404-worktree-config.sh
@@ -78,4 +78,20 @@ test_expect_success 'config.worktree no longer read without extension' '
test_cmp_config -C wt2 shared this.is
'
+test_expect_success 'correctly read config.worktree from submodules' '
+ test_unconfig extensions.worktreeConfig &&
+ git init sub &&
+ (
+ cd sub &&
+ test_commit A &&
+ git config extensions.worktreeConfig true &&
+ git config --worktree wtconfig.sub test-value
+ ) &&
+ git submodule add ./sub &&
+ git commit -m "add sub" &&
+ echo test-value >expect &&
+ test-tool config --submodule=sub get_value wtconfig.sub >actual &&
+ test_cmp expect actual
+'
+
test_done
--
2.28.0
^ permalink raw reply related
* [PATCH v5 5/8] t/helper/test-config: unify exit labels
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
test-config's main function has three different exit labels, all of
which have to perform the same cleanup code before returning. Unify the
labels in preparation for the next patch which will increase the cleanup
section.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
t/helper/test-config.c | 51 +++++++++++++++++-------------------------
1 file changed, 20 insertions(+), 31 deletions(-)
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 26d9c2ac4c..8fe43e9775 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -69,16 +69,19 @@ static int early_config_cb(const char *var, const char *value, void *vdata)
return 0;
}
+#define TC_VALUE_NOT_FOUND 1
+#define TC_CONFIG_FILE_ERROR 2
+
int cmd__config(int argc, const char **argv)
{
- int i, val;
+ int i, val, ret = 0;
const char *v;
const struct string_list *strptr;
struct config_set cs;
if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
read_early_config(early_config_cb, (void *)argv[2]);
- return 0;
+ return ret;
}
setup_git_directory();
@@ -94,10 +97,9 @@ int cmd__config(int argc, const char **argv)
printf("(NULL)\n");
else
printf("%s\n", v);
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
strptr = git_config_get_value_multi(argv[2]);
@@ -109,41 +111,38 @@ int cmd__config(int argc, const char **argv)
else
printf("%s\n", v);
}
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
if (!git_config_get_int(argv[2], &val)) {
printf("%d\n", val);
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
if (!git_config_get_bool(argv[2], &val)) {
printf("%d\n", val);
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc == 3 && !strcmp(argv[1], "get_string")) {
if (!git_config_get_string_tmp(argv[2], &v)) {
printf("%s\n", v);
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
- goto exit2;
+ ret = TC_CONFIG_FILE_ERROR;
+ goto out;
}
}
if (!git_configset_get_value(&cs, argv[2], &v)) {
@@ -151,17 +150,17 @@ int cmd__config(int argc, const char **argv)
printf("(NULL)\n");
else
printf("%s\n", v);
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
- goto exit2;
+ ret = TC_CONFIG_FILE_ERROR;
+ goto out;
}
}
strptr = git_configset_get_value_multi(&cs, argv[2]);
@@ -173,27 +172,17 @@ int cmd__config(int argc, const char **argv)
else
printf("%s\n", v);
}
- goto exit0;
} else {
printf("Value not found for \"%s\"\n", argv[2]);
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
} else if (!strcmp(argv[1], "iterate")) {
git_config(iterate_cb, NULL);
- goto exit0;
+ } else {
+ die("%s: Please check the syntax and the function name", argv[0]);
}
- die("%s: Please check the syntax and the function name", argv[0]);
-
-exit0:
- git_configset_clear(&cs);
- return 0;
-
-exit1:
- git_configset_clear(&cs);
- return 1;
-
-exit2:
+out:
git_configset_clear(&cs);
- return 2;
+ return ret;
}
--
2.28.0
^ permalink raw reply related
* [PATCH v5 4/8] t/helper/test-config: check argc before accessing argv
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
Check that we have the expected argc in 'configset_get_value' and
'configset_get_value_multi' before trying to access argv elements.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
t/helper/test-config.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 9e9d50099a..26d9c2ac4c 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -138,7 +138,7 @@ int cmd__config(int argc, const char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
- } else if (!strcmp(argv[1], "configset_get_value")) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ -156,7 +156,7 @@ int cmd__config(int argc, const char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
- } else if (!strcmp(argv[1], "configset_get_value_multi")) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
--
2.28.0
^ permalink raw reply related
* [PATCH v5 3/8] t/helper/test-config: be consistent with exit codes
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
The test-config helper can return at least three different exit codes to
reflect the status of the requested operation. And these codes are
checked in some of the tests. But there is an inconsistent place in the
helper where an usage error returns the same code as a "value not found"
error. Let's fix that and, while we are here, document the meaning of
each exit code in the file's header.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
t/helper/test-config.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index a6e936721f..9e9d50099a 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -30,6 +30,11 @@
* iterate -> iterate over all values using git_config(), and print some
* data for each
*
+ * Exit codes:
+ * 0: success
+ * 1: value not found for the given config key
+ * 2: config file path given as argument is inaccessible or doesn't exist
+ *
* Examples:
*
* To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -80,10 +85,10 @@ int cmd__config(int argc, const char **argv)
git_configset_init(&cs);
- if (argc < 2) {
- fprintf(stderr, "Please, provide a command name on the command-line\n");
- goto exit1;
- } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
+ if (argc < 2)
+ die("Please, provide a command name on the command-line");
+
+ if (argc == 3 && !strcmp(argv[1], "get_value")) {
if (!git_config_get_value(argv[2], &v)) {
if (!v)
printf("(NULL)\n");
--
2.28.0
^ permalink raw reply related
* [PATCH v5 2/8] t1308-config-set: avoid false positives when using test-config
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
One test in t1308 expects test-config to fail with exit code 128 due to
a parsing error in the config machinery. But test-config might also exit
with 128 for any other reason that leads it to call die(). Therefore the
test can potentially succeed for the wrong reason. To avoid false
positives, let's check test-config's output, in addition to the exit
code, and make sure that the cause of the error is the one we expect in
this test.
Moreover, the test was using the auxiliary function check_config which
optionally takes a string to compare the test-config stdout against.
Because this string is optional, there is a risk that future callers may
also check only the exit code and not the output. To avoid that, make
the string parameter of this function mandatory.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
t/t1308-config-set.sh | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 3a527e3a84..cff17120dc 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -14,10 +14,7 @@ check_config () {
expect_code=0
fi &&
op=$1 key=$2 && shift && shift &&
- if test $# != 0
- then
- printf "%s\n" "$@"
- fi >expect &&
+ printf "%s\n" "$@" >expect &&
test_expect_code $expect_code test-tool config "$op" "$key" >actual &&
test_cmp expect actual
}
@@ -130,7 +127,8 @@ test_expect_success 'check line error when NULL string is queried' '
'
test_expect_success 'find integer if value is non parse-able' '
- check_config expect_code 128 get_int lamb.head
+ test_expect_code 128 test-tool config get_int lamb.head 2>result &&
+ test_i18ngrep "fatal: bad numeric config value '\'none\'' for '\'lamb.head\''" result
'
test_expect_success 'find bool value for the entered key' '
--
2.28.0
^ permalink raw reply related
* [PATCH v5 0/8] grep: honor sparse checkout and add option to ignore it
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1591974940.git.matheus.bernardino@usp.br>
This series makes git-grep restrict its output to the sparsity patterns when
requested by the user. A new global option is added to control this behavior
in grep and hopefully more commands in the future. There are also a
couple fixes in t/helper/test-config and in a test that uses it.
Changes since v4:
- Rebased on top of master to use repo_config_get_string_tmp(), added in
jk/leakfix, in t/helper/test-config (patch 6).
- Added patch 2, to make sure a test that relies on test-config checks its
output in addition to the exit code, to avoid false positives.
- Split patch "t/helper/test-config: return exit codes consistently" into
three separated ones, as these are in fact three non-related changes:
"t/helper/test-config: unify exit labels"
"t/helper/test-config: check argc before accessing argv"
"t/helper/test-config: be consistent with exit codes"
- Removed TC_USAGE_ERROR in favor of calling die(). Also removed the
test_config_exit_code enum.
- On "config: correctly read worktree configs in submodules":
* Improved commit message to focus on the problem instead of the
implementation and remove section about the grep example.
* Made use of the parse_options API
* Allocated subrepo struct in the stack instead of malloc()'ing.
Matheus Tavares (8):
doc: grep: unify info on configuration variables
t1308-config-set: avoid false positives when using test-config
t/helper/test-config: be consistent with exit codes
t/helper/test-config: check argc before accessing argv
t/helper/test-config: unify exit labels
config: correctly read worktree configs in submodules
grep: honor sparse checkout patterns
config: add setting to ignore sparsity patterns in some cmds
Documentation/config.txt | 2 +
Documentation/config/grep.txt | 18 +-
Documentation/config/sparse.txt | 20 ++
Documentation/git-grep.txt | 36 +--
Documentation/git.txt | 4 +
Makefile | 1 +
builtin/grep.c | 134 ++++++++++-
config.c | 21 +-
contrib/completion/git-completion.bash | 2 +
git.c | 5 +
sparse-checkout.c | 18 ++
sparse-checkout.h | 11 +
t/helper/test-config.c | 126 ++++++----
t/t1308-config-set.sh | 8 +-
t/t2404-worktree-config.sh | 16 ++
t/t7011-skip-worktree-reading.sh | 9 -
t/t7817-grep-sparse-checkout.sh | 321 +++++++++++++++++++++++++
t/t9902-completion.sh | 4 +-
18 files changed, 652 insertions(+), 104 deletions(-)
create mode 100644 Documentation/config/sparse.txt
create mode 100644 sparse-checkout.c
create mode 100644 sparse-checkout.h
create mode 100755 t/t7817-grep-sparse-checkout.sh
Range-diff against v4:
1: fc47a96bfa = 1: 70c9a4e741 doc: grep: unify info on configuration variables
-: ---------- > 2: f53782f14c t1308-config-set: avoid false positives when using test-config
-: ---------- > 3: 85e1588d6c t/helper/test-config: be consistent with exit codes
-: ---------- > 4: 0750191342 t/helper/test-config: check argc before accessing argv
2: 874aab36dd ! 5: 56535b0e36 t/helper/test-config: return exit codes consistently
@@ Metadata
Author: Matheus Tavares <matheus.bernardino@usp.br>
## Commit message ##
- t/helper/test-config: return exit codes consistently
+ t/helper/test-config: unify exit labels
- The test-config helper may exit with a variety of at least four
- different codes, to reflect the status of the requested operations.
- These codes are sometimes checked in the tests, but not all of the codes
- are returned consistently by the helper: 1 will usually refer to a
- "value not found", but usage errors can also return 1 or 128. Moreover,
- 128 is also expected on errors within the configset functions. These
- inconsistent uses of the exit codes can lead to false positives in the
- tests. Although all tests which expect errors and check the helper's
- exit code currently also check the output, it's still better to
- standardize the exit codes and avoid future problems in new tests.
- While we are here, let's also check that we have the expected argc for
- configset_get_value and configset_get_value_multi, before trying to use
- argv.
-
- Note: this change is implemented with the unification of the exit
- labels. This might seem unnecessary, for now, but it will benefit the
- next patch, which will increase the cleanup section.
+ test-config's main function has three different exit labels, all of
+ which have to perform the same cleanup code before returning. Unify the
+ labels in preparation for a future patch which will increase the cleanup
+ section.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
## t/helper/test-config.c ##
-@@
- * iterate -> iterate over all values using git_config(), and print some
- * data for each
- *
-+ * Exit codes:
-+ * 0: success
-+ * 1: value not found for the given config key
-+ * 2: config file path given as argument is inaccessible or doesn't exist
-+ * 129: test-config usage error
-+ *
-+ * Note: tests may also expect 128 for die() calls in the config machinery.
-+ *
- * Examples:
- *
- * To print the value with highest priority for key "foo.bAr Baz.rock":
@@ t/helper/test-config.c: static int early_config_cb(const char *var, const char *value, void *vdata)
return 0;
}
-+enum test_config_exit_code {
-+ TC_SUCCESS = 0,
-+ TC_VALUE_NOT_FOUND = 1,
-+ TC_CONFIG_FILE_ERROR = 2,
-+ TC_USAGE_ERROR = 129,
-+};
++#define TC_VALUE_NOT_FOUND 1
++#define TC_CONFIG_FILE_ERROR 2
+
int cmd__config(int argc, const char **argv)
{
- int i, val;
+- int i, val;
++ int i, val, ret = 0;
const char *v;
const struct string_list *strptr;
struct config_set cs;
-+ enum test_config_exit_code ret = TC_SUCCESS;
if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
read_early_config(early_config_cb, (void *)argv[2]);
- return 0;
-+ return TC_SUCCESS;
++ return ret;
}
setup_git_directory();
-
- git_configset_init(&cs);
-
-- if (argc < 2) {
-- fprintf(stderr, "Please, provide a command name on the command-line\n");
-- goto exit1;
-- } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
-+ if (argc < 2)
-+ goto print_usage_error;
-+
-+ if (argc == 3 && !strcmp(argv[1], "get_value")) {
- if (!git_config_get_value(argv[2], &v)) {
- if (!v)
+@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
printf("(NULL)\n");
else
printf("%s\n", v);
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
-- } else if (!strcmp(argv[1], "configset_get_value")) {
-+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
- goto exit1;
+ ret = TC_VALUE_NOT_FOUND;
}
-- } else if (!strcmp(argv[1], "configset_get_value_multi")) {
-+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
git_config(iterate_cb, NULL);
- goto exit0;
+ } else {
-+print_usage_error:
-+ fprintf(stderr, "Invalid syntax. Usage: test-tool config <cmd> [args]\n");
-+ ret = TC_USAGE_ERROR;
++ die("%s: Please check the syntax and the function name", argv[0]);
}
- die("%s: Please check the syntax and the function name", argv[0]);
3: c5093099f3 < -: ---------- t/helper/test-config: facilitate addition of new cli options
4: b510de0de0 ! 6: 3e02e1bd24 config: correctly read worktree configs in submodules
@@ Metadata
## Commit message ##
config: correctly read worktree configs in submodules
- One of the steps in do_git_config_sequence() is to load the
- worktree-specific config file. Although the function receives a git_dir
- string, it relies on git_pathdup(), which uses the_repository->git_dir,
- to make the path to the file. Furthermore, it also checks that
- extensions.worktreeConfig is set through the
- repository_format_worktree_config variable, which refers to
- the_repository only. Thus, when a submodule has worktree-specific
- settings, a command executed in the superproject that recurses into the
- submodule won't find the said settings.
+ The config machinery is not able to read worktree configs from a
+ submodule in a process where the_repository represents the superproject.
+ Furthermore, when extensions.worktreeConfig is set on the superproject,
+ querying for a worktree config in a submodule will, instead, return
+ the value set at the superproject.
- This will be especially important in the next patch: git-grep will learn
- to honor sparse checkouts and, when running with --recurse-submodules,
- the submodule's sparse checkout settings must be loaded. As these
- settings are stored in the config.worktree file, they would be ignored
- without this patch. So let's fix this by reading the right
- config.worktree file and extensions.worktreeConfig setting, based on the
- git_dir and commondir paths given to do_git_config_sequence(). Also
- add a test to avoid any regressions.
+ The problem resides in do_git_config_sequence(). Although the function
+ receives a git_dir string, it uses the_repository->git_dir when making
+ the path to the worktree config file. And when checking if
+ extensions.worktreeConfig is set, it uses the global
+ repository_format_worktree_config variable, which refers to
+ the_repository only. So let's fix this by using the git_dir given to the
+ function and reading the extension value from the right place. Also add
+ a test to avoid any regressions.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
@@ t/helper/test-config.c
#include "config.h"
#include "string-list.h"
+#include "submodule-config.h"
++#include "parse-options.h"
/*
* This program exposes the C API of the configuration mechanism
@@ t/helper/test-config.c
*
* get_value -> prints the value with highest priority for the entered key
*
-@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
+@@ t/helper/test-config.c: static int early_config_cb(const char *var, const char *value, void *vdata)
+ #define TC_VALUE_NOT_FOUND 1
+ #define TC_CONFIG_FILE_ERROR 2
+
++static const char *test_config_usage[] = {
++ "test-tool config [--submodule=<path>] <cmd> [<args>]",
++ NULL
++};
++
+ int cmd__config(int argc, const char **argv)
+ {
+ int i, val, ret = 0;
+ const char *v;
const struct string_list *strptr;
- struct config_set cs = { .hash_initialized = 0 };
- enum test_config_exit_code ret = TC_SUCCESS;
-+ struct repository *repo = the_repository;
+ struct config_set cs;
++ struct repository subrepo, *repo = the_repository;
+ const char *subrepo_path = NULL;
-
- argc--; /* skip over "config" */
- argv++;
-@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
- if (argc == 0)
- goto print_usage_error;
-
-+ if (skip_prefix(*argv, "--submodule=", &subrepo_path)) {
-+ argc--;
-+ argv++;
-+ if (argc == 0)
-+ goto print_usage_error;
-+ }
+
- if (argc == 2 && !strcmp(argv[0], "read_early_config")) {
-+ if (subrepo_path) {
-+ fprintf(stderr, "Cannot use --submodule with read_early_config\n");
-+ return TC_USAGE_ERROR;
-+ }
- read_early_config(early_config_cb, (void *)argv[1]);
- return TC_SUCCESS;
++ struct option options[] = {
++ OPT_STRING(0, "submodule", &subrepo_path, "path",
++ "run <cmd> on the submodule at <path>"),
++ OPT_END()
++ };
++
++ argc = parse_options(argc, argv, NULL, options, test_config_usage,
++ PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_STOP_AT_NON_OPTION);
++ if (argc < 2)
++ die("Please, provide a command name on the command-line");
+
+ if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
++ if (subrepo_path)
++ die("cannot use --submodule with read_early_config");
+ read_early_config(early_config_cb, (void *)argv[2]);
+ return ret;
}
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
- setup_git_directory();
+
git_configset_init(&cs);
+- if (argc < 2)
+- die("Please, provide a command name on the command-line");
+ if (subrepo_path) {
+ const struct submodule *sub;
-+ struct repository *subrepo = xcalloc(1, sizeof(*repo));
+
+ sub = submodule_from_path(the_repository, &null_oid, subrepo_path);
-+ if (!sub || repo_submodule_init(subrepo, the_repository, sub)) {
-+ fprintf(stderr, "Invalid argument to --submodule: '%s'\n",
-+ subrepo_path);
-+ free(subrepo);
-+ ret = TC_USAGE_ERROR;
-+ goto out;
-+ }
-+ repo = subrepo;
-+ }
++ if (!sub || repo_submodule_init(&subrepo, the_repository, sub))
++ die("invalid argument to --submodule: '%s'", subrepo_path);
+
- if (argc == 2 && !strcmp(argv[0], "get_value")) {
-- if (!git_config_get_value(argv[1], &v)) {
-+ if (!repo_config_get_value(repo, argv[1], &v)) {
++ repo = &subrepo;
++ }
+
+ if (argc == 3 && !strcmp(argv[1], "get_value")) {
+- if (!git_config_get_value(argv[2], &v)) {
++ if (!repo_config_get_value(repo, argv[2], &v)) {
if (!v)
printf("(NULL)\n");
else
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc == 2 && !strcmp(argv[0], "get_value_multi")) {
-- strptr = git_config_get_value_multi(argv[1]);
-+ strptr = repo_config_get_value_multi(repo, argv[1]);
+ } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
+- strptr = git_config_get_value_multi(argv[2]);
++ strptr = repo_config_get_value_multi(repo, argv[2]);
if (strptr) {
for (i = 0; i < strptr->nr; i++) {
v = strptr->items[i].string;
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc == 2 && !strcmp(argv[0], "get_int")) {
-- if (!git_config_get_int(argv[1], &val)) {
-+ if (!repo_config_get_int(repo, argv[1], &val)) {
+ } else if (argc == 3 && !strcmp(argv[1], "get_int")) {
+- if (!git_config_get_int(argv[2], &val)) {
++ if (!repo_config_get_int(repo, argv[2], &val)) {
printf("%d\n", val);
} else {
- printf("Value not found for \"%s\"\n", argv[1]);
+ printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc == 2 && !strcmp(argv[0], "get_bool")) {
-- if (!git_config_get_bool(argv[1], &val)) {
-+ if (!repo_config_get_bool(repo, argv[1], &val)) {
+ } else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
+- if (!git_config_get_bool(argv[2], &val)) {
++ if (!repo_config_get_bool(repo, argv[2], &val)) {
printf("%d\n", val);
} else {
+
- printf("Value not found for \"%s\"\n", argv[1]);
+ printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc == 2 && !strcmp(argv[0], "get_string")) {
-- if (!git_config_get_string_tmp(argv[1], &v)) {
-+ if (!repo_config_get_string_tmp(repo, argv[1], &v)) {
+ } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
+- if (!git_config_get_string_tmp(argv[2], &v)) {
++ if (!repo_config_get_string_tmp(repo, argv[2], &v)) {
printf("%s\n", v);
} else {
- printf("Value not found for \"%s\"\n", argv[1]);
+ printf("Value not found for \"%s\"\n", argv[2]);
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc >= 2 && !strcmp(argv[0], "configset_get_value")) {
-+ if (subrepo_path) {
-+ fprintf(stderr, "Cannot use --submodule with configset_get_value\n");
-+ ret = TC_USAGE_ERROR;
-+ goto out;
-+ }
- for (i = 2; i < argc; i++) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
++ if (subrepo_path)
++ die("cannot use --submodule with configset_get_value");
++
+ for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
- } else if (argc >= 2 && !strcmp(argv[0], "configset_get_value_multi")) {
-+ if (subrepo_path) {
-+ fprintf(stderr, "Cannot use --submodule with configset_get_value_multi\n");
-+ ret = TC_USAGE_ERROR;
-+ goto out;
-+ }
- for (i = 2; i < argc; i++) {
+ } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
++ if (subrepo_path)
++ die("cannot use --submodule with configset_get_value_multi");
++
+ for (i = 3; i < argc; i++) {
int err;
if ((err = git_configset_add_file(&cs, argv[i]))) {
@@ t/helper/test-config.c: int cmd__config(int argc, const char **argv)
ret = TC_VALUE_NOT_FOUND;
}
- } else if (!strcmp(argv[0], "iterate")) {
+ } else if (!strcmp(argv[1], "iterate")) {
- git_config(iterate_cb, NULL);
+ repo_config(repo, iterate_cb, NULL);
} else {
- print_usage_error:
-- fprintf(stderr, "Invalid syntax. Usage: test-tool config <cmd> [args]\n");
-+ fprintf(stderr, "Invalid syntax. Usage: test-tool config"
-+ " [--submodule=<path>] <cmd> [args]\n");
- ret = TC_USAGE_ERROR;
+ die("%s: Please check the syntax and the function name", argv[0]);
}
out:
git_configset_clear(&cs);
-+ if (repo != the_repository) {
++ if (repo != the_repository)
+ repo_clear(repo);
-+ free(repo);
-+ }
return ret;
}
5: 6d9720abf5 = 7: 902556a7b6 grep: honor sparse checkout patterns
6: affb931d35 = 8: 70e7d7b90c config: add setting to ignore sparsity patterns in some cmds
--
2.28.0
^ permalink raw reply
* [PATCH v5 1/8] doc: grep: unify info on configuration variables
From: Matheus Tavares @ 2020-09-02 6:17 UTC (permalink / raw)
To: git; +Cc: gitster, stolee, newren, jonathantanmy, jrnieder
In-Reply-To: <cover.1599026986.git.matheus.bernardino@usp.br>
Explanations about the configuration variables for git-grep are
duplicated in "Documentation/git-grep.txt" and
"Documentation/config/grep.txt", which can make maintenance difficult.
The first also contains a definition not present in the latter
(grep.fullName). To avoid problems like this, let's unify the
information in the second file and include it in the first.
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
Documentation/config/grep.txt | 10 ++++++++--
Documentation/git-grep.txt | 36 ++++++-----------------------------
2 files changed, 14 insertions(+), 32 deletions(-)
diff --git a/Documentation/config/grep.txt b/Documentation/config/grep.txt
index 44abe45a7c..dd51db38e1 100644
--- a/Documentation/config/grep.txt
+++ b/Documentation/config/grep.txt
@@ -16,8 +16,14 @@ grep.extendedRegexp::
other than 'default'.
grep.threads::
- Number of grep worker threads to use.
- See `grep.threads` in linkgit:git-grep[1] for more information.
+ Number of grep worker threads to use. See `--threads`
+ifndef::git-grep[]
+ in linkgit:git-grep[1]
+endif::git-grep[]
+ for more information.
+
+grep.fullName::
+ If set to true, enable `--full-name` option by default.
grep.fallbackToNoIndex::
If set to true, fall back to git grep --no-index if git grep
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index a7f9bc99ea..9bdf807584 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -41,34 +41,8 @@ characters. An empty string as search expression matches all lines.
CONFIGURATION
-------------
-grep.lineNumber::
- If set to true, enable `-n` option by default.
-
-grep.column::
- If set to true, enable the `--column` option by default.
-
-grep.patternType::
- Set the default matching behavior. Using a value of 'basic', 'extended',
- 'fixed', or 'perl' will enable the `--basic-regexp`, `--extended-regexp`,
- `--fixed-strings`, or `--perl-regexp` option accordingly, while the
- value 'default' will return to the default matching behavior.
-
-grep.extendedRegexp::
- If set to true, enable `--extended-regexp` option by default. This
- option is ignored when the `grep.patternType` option is set to a value
- other than 'default'.
-
-grep.threads::
- Number of grep worker threads to use. If unset (or set to 0), Git will
- use as many threads as the number of logical cores available.
-
-grep.fullName::
- If set to true, enable `--full-name` option by default.
-
-grep.fallbackToNoIndex::
- If set to true, fall back to git grep --no-index if git grep
- is executed outside of a git repository. Defaults to false.
-
+:git-grep: 1
+include::config/grep.txt[]
OPTIONS
-------
@@ -269,8 +243,10 @@ providing this option will cause it to die.
found.
--threads <num>::
- Number of grep worker threads to use.
- See `grep.threads` in 'CONFIGURATION' for more information.
+ Number of grep worker threads to use. If not provided (or set to
+ 0), Git will use as many worker threads as the number of logical
+ cores available. The default value can also be set with the
+ `grep.threads` configuration.
-f <file>::
Read patterns from <file>, one per line.
--
2.28.0
^ permalink raw reply related
* Re: [PATCH] Makefile: add support for generating JSON compilation database
From: brian m. carlson @ 2020-09-02 1:33 UTC (permalink / raw)
To: Jeff King
Cc: Junio C Hamano, Philippe Blain via GitGitGadget, git,
Philippe Blain
In-Reply-To: <20200901073827.GA3967005@coredump.intra.peff.net>
[-- Attachment #1: Type: text/plain, Size: 3162 bytes --]
On 2020-09-01 at 07:38:27, Jeff King wrote:
> Likewise. Looking at the output, I'm confused how it would help with
> things like searching and refactoring. It might be nice to spell it out
> for those of us exposed to it for the first time (I tried following the
> links but remained unenlightened).
Traditionally, editors had to learn about every language if they wanted
to add special functionality like refactoring (e.g., renaming "struct
foo" to "struct bar"), finding all the instances of a type, finding
where a type or function was declared, or similar IDE features. When
Microsoft developed Visual Studio Code, they decided that they did not
want to implement this functionality for every language under the sun,
and instead developed the Language Server Protocol[0].
With LSP, each editor needs functionality to speak its portion (either
natively, as with VS Code, or with a plugin, such as Vim's ALE) and each
language implements a language server to implement its part of the
functionality. The protocol is capability based, so implementations can
support those features which make sense for their editor or language and
omit those which don't. This way, all editors can benefit and language
communities can implement one program to provide features, and the
problem becomes an O(M + N) problem instead of an O(M * N) problem.
In some languages, like Rust, it's pretty obvious how to compile your
project: you use cargo, the built-in build tool. There is also a
standard layout to find and enumerate files within a project. However,
C is not so standardized, so clangd, which is a clang-based C and C++
LSP implementation, needs help to find out which flags are needed to
compile, and therefore find the header files to make sense of parsing
the C code and implementing its side of the protocol. That's what this
patch implements.
I use Vim and ALE extensively, and it pretty much just works for most
languages, including Go and Rust, once you install the LSP server. Git
is one of the few projects I work on which is still C and therefore
needs help here.
Hopefully this is at least more enlightening about the functionality
that clangd provides, why it's interesting, how it works, and why it's
valuable.
> I'd also be curious to hear what advantages it gives to add a new
> Makefile knob rather than just letting interested parties add -MJ to
> their CFLAGS. Is it just a convenience to create the concatenated form?
> It seems weird that projects would need to do so themselves with sed
> hackery (i.e., I'd expect whatever consumes this json to be able to
> handle multiple files).
I believe clangd does need the concatenated form, and at least the ALE
plugin for Vim uses that specific file name to detect whether clangd
should be used. The problem is that clangd doesn't know where your
source code is actually located and it's very expensive to traverse an
entire repository which might contain literally millions of files if
you're only really interested in a handful.
[0] https://microsoft.github.io/language-server-protocol/
--
brian m. carlson: Houston, Texas, US
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 263 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] ci: avoid ugly "failure" in the `ci-config` job
From: Jeff King @ 2020-09-02 0:40 UTC (permalink / raw)
To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin
In-Reply-To: <b92374e69192d57bcb11fb2573beb4e9aee339a9.1598991568.git.gitgitgadget@gmail.com>
On Tue, Sep 01, 2020 at 08:19:27PM +0000, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> In the common case where users have _not_ pushed a `ci-config` branch to
> configure which branches should be included in the GitHub workflow runs,
> there is a big fat ugly annotation about a failure in the run's log:
>
> X Check failure on line 1 in .github
>
> @github-actions github-actions / ci-config
>
> .github#L1
>
> Process completed with exit code 128.
>
> The reason is that the `ci-config` job tries to clone that `ci-config`
> branch, and even if it is configured to continue on error, the
> annotation is displayed, and it is distracting.
Hmm. I thought we handled this with the "continue-on-error" flag.
Unsurprisingly I have a ci-config branch in my repo, but git/git
doesn't, and here's a sample run there:
https://github.com/git/git/runs/1053619435?check_suite_focus=true
Both the "ci-config" task, as well as the individual "try to clone
ci-config branch" step are marked with a green check.
...Oh, I think I see what you mean. In the "Annotations" summary we
still see an ugly "X" box.
> Let's just handle this on the shell script level, so that the job's step
> is not marked as a failure.
OK, that makes sense. We could do differentiate clone failing versus cd
versus checkout (or for that matter, clone failing because the branch
doesn't exist versus a network error). But it's probably not worth
getting too fancy.
My next question was going to be: should we also drop the
continue-on-error flag? But I see you did that already.
So the patch looks good to me. Sorry for introducing CI noise in the
first place. :)
-Peff
^ permalink raw reply
* Bug report: git cat-file -e / rev-list disagree with git fsck on empty tree
From: Anish R Athalye @ 2020-09-02 0:27 UTC (permalink / raw)
To: git@vger.kernel.org
This is related to the change made in f06ab027efd2 (rev-list: allow cached
objects in existence check).
That patch seemed designed to allow the workflow where the empty tree is
missing from the object store, so
`git cat-file -e 4b825dc642cb6eb9a060e54bf8d69288fbee4904` and
`git rev-list --objects 4b825dc642cb6eb9a060e54bf8d69288fbee4904`
both return success even when the object is not physically present.
However, in the same situation:
$ git fsck
[...]
missing tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
I'm not sure if this is the intended behavior (the tree is indeed missing, so
in some sense, this is reasonable). But it seems somewhat confusing that it
disagrees with the interrogation commands.
^ permalink raw reply
* Re: [PATCH 1/2] ci: fix indentation of the `ci-config` job
From: Jeff King @ 2020-09-02 0:33 UTC (permalink / raw)
To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin
In-Reply-To: <b5363e282f69570e34ffb806f7a62e00e39b98bc.1598991568.git.gitgitgadget@gmail.com>
On Tue, Sep 01, 2020 at 08:19:26PM +0000, Johannes Schindelin via GitGitGadget wrote:
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> The section added in e76eec35540f (ci: allow per-branch config for
> GitHub Actions, 2020-05-07) contains a `&&`-chain that connects several
> commands. The first command is actually so long that it stretches over
> multiple lines, and as per usual, the continuation lines are indented one
> more level than the first.
>
> However, the subsequent commands in the `&&`-chain were also indented
> one more level than the first command, which was almost certainly
> unintended.
Yeah, I'm pretty sure this was unintentional in my original (and got
carried through the recent re-indentation).
-Peff
^ permalink raw reply
* Re: [PATCH] core.abbrev <off|false|no> disables abbreviations
From: brian m. carlson @ 2020-09-01 23:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Derrick Stolee, Eric Wong, git
In-Reply-To: <xmqqblipebto.fsf@gitster.c.googlers.com>
[-- Attachment #1: Type: text/plain, Size: 1375 bytes --]
On 2020-09-01 at 15:49:55, Junio C Hamano wrote:
> I was in the vicinity of this code recently for reviewing another
> topic, but IIRC, 0 came from the UI level does get rounded up to the
> minimum accepted and never reach "default_abbrev", but if you manage
> to place 0 or -1 in default_abbrev here (e.g. with additional code,
> like the above part with the right hand side of the assignment
> updated), I think the value will propagate throughout the codepath
> and causes the downstream code to do the right thing. 0 will give
> you no-abbreviation (i.e. full length depending on the length of the
> hash) and -1 will give you the "scale as appropriate for the size of
> the object store".
>
> I have mild preference for using 0 over hardcoded single "full
> length" here. Even though we currently do not plan to allow
> multiple hashes in use simultaneously in a single invocation of Git,
> if that ever happens, we will regret hardcoding the_hash_algo->hexsz
> on the right hand side of the assignment here, like this patch does.
I think we have some commands that accept --abbrev=0 as a value meaning
"no abbreviation", because I've touched that code as part of the SHA-256
work. So as far as the option value is concerned, I think it may make
sense to use 0 for that meaning and just document it.
--
brian m. carlson: Houston, Texas, US
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 263 bytes --]
^ permalink raw reply
* [PATCH v2] Makefile: add support for generating JSON compilation database
From: Philippe Blain via GitGitGadget @ 2020-09-01 23:09 UTC (permalink / raw)
To: git
Cc: brian m. carlson, Philippe Blain, Jeff King, Philippe Blain,
Philippe Blain
In-Reply-To: <pull.714.git.1598815707540.gitgitgadget@gmail.com>
From: Philippe Blain <levraiphilippeblain@gmail.com>
Tools based on LibClang [1] can make use of a 'JSON Compilation
Database' [2] that keeps track of the exact options used to compile a set
of source files.
For example, clangd [3], which is a C language server protocol
implementation, can use a JSON compilation database to determine the
flags needed to compile a file so it can provide proper editor
integration. As a result, editors supporting the language server
protocol (such as VS Code, Emacs, or Vim, with suitable plugins) can
provide better searching, integration, and refactoring tools.
The Clang compiler can generate JSON fragments when compiling [4],
using the `-MJ` flag. These JSON fragments (one per compiled source
file) can then be concatenated to create the compilation database,
commonly called 'compile_commands.json'.
Add support to the Makefile for generating these JSON fragments as well
as the compilation database itself, if the environment variable
'GENERATE_COMPILATION_DATABASE' is set.
If this variable is set, check that $(CC) indeed supports the `-MJ`
flag, following what is done for automatic dependencies.
All JSON fragments are placed in the 'compile_commands/' directory, and
the compilation database 'compile_commands.json' is generated as a
dependency of the 'all' target using a `sed` invocation.
[1] https://clang.llvm.org/docs/Tooling.html
[2] https://clang.llvm.org/docs/JSONCompilationDatabase.html
[3] https://clangd.llvm.org/
[4] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mj-arg
Helped-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
---
Add support for generating JSON compilation database
Changes since v1:
* Added a paragraph to the commit message to better explain why this
feature would help Git developers (Thanks Brian!)
* Corrected the description of the new GENERATE_COMPILATION_DATABASE
Makefile knob to make it reflect its actual behavior (cf.
https://lore.kernel.org/git/FC95CFF7-F9DA-4CDA-9923-99C3432DCAD5@gmail.com/
)
v1: I don't have a lot of knowledge of Make double-colon rules, or
insight into why they are used for the 'all' target, but I think the
approach I chose makes sense. In particular, I do not list any
prerequisite for the 'compile_commands.json' file, but from what I
tested it is still rebuilt anytime the 'all' target is rebuilt, which is
what we want.
Note: CMakeLists.txt in contrib/buildsystems does not need to be updated
to also support this feature because CMake supports it out-of-the-box
[1].
[1]
https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-714%2Fphil-blain%2Fcompiledb-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-714/phil-blain/compiledb-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/714
Range-diff vs v1:
1: 411fefaafb ! 1: da9544e4aa Makefile: add support for generating JSON compilation database
@@ Commit message
Database' [2] that keeps track of the exact options used to compile a set
of source files.
- The Clang compiler can generate JSON fragments when compiling [3],
+ For example, clangd [3], which is a C language server protocol
+ implementation, can use a JSON compilation database to determine the
+ flags needed to compile a file so it can provide proper editor
+ integration. As a result, editors supporting the language server
+ protocol (such as VS Code, Emacs, or Vim, with suitable plugins) can
+ provide better searching, integration, and refactoring tools.
+
+ The Clang compiler can generate JSON fragments when compiling [4],
using the `-MJ` flag. These JSON fragments (one per compiled source
file) can then be concatenated to create the compilation database,
commonly called 'compile_commands.json'.
@@ Commit message
[1] https://clang.llvm.org/docs/Tooling.html
[2] https://clang.llvm.org/docs/JSONCompilationDatabase.html
- [3] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mj-arg
+ [3] https://clangd.llvm.org/
+ [4] https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mj-arg
+ Helped-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
## .gitignore ##
@@ Makefile: all::
+# Define GENERATE_COMPILATION_DATABASE to generate JSON compilation database
+# entries during compilation if your compiler supports it, using the `-MJ` flag.
+# The JSON entries will be placed in the `compile_commands/` directory,
-+# and the JSON compilation database can be created afterwards with
-+# `make compile_commands.json`.
++# and the JSON compilation database 'compile_commands.json' will be created
++# at the root of the repository.
+#
# Define DEVELOPER to enable more compiler warnings. Compiler version
# and family are auto detected, but could be overridden by defining
.gitignore | 2 ++
Makefile | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/.gitignore b/.gitignore
index ee509a2ad2..f4c51300e0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -197,6 +197,7 @@
/git.spec
*.exe
*.[aos]
+*.o.json
*.py[co]
.depend/
*.gcda
@@ -218,6 +219,7 @@
/tags
/TAGS
/cscope*
+/compile_commands.json
*.hcc
*.obj
*.lib
diff --git a/Makefile b/Makefile
index 65f8cfb236..51cd0f302b 100644
--- a/Makefile
+++ b/Makefile
@@ -462,6 +462,12 @@ all::
# the global variable _wpgmptr containing the absolute path of the current
# executable (this is the case on Windows).
#
+# Define GENERATE_COMPILATION_DATABASE to generate JSON compilation database
+# entries during compilation if your compiler supports it, using the `-MJ` flag.
+# The JSON entries will be placed in the `compile_commands/` directory,
+# and the JSON compilation database 'compile_commands.json' will be created
+# at the root of the repository.
+#
# Define DEVELOPER to enable more compiler warnings. Compiler version
# and family are auto detected, but could be overridden by defining
# COMPILER_FEATURES (see config.mak.dev). You can still set
@@ -1258,6 +1264,20 @@ $(error please set COMPUTE_HEADER_DEPENDENCIES to yes, no, or auto \
endif
endif
+ifdef GENERATE_COMPILATION_DATABASE
+compdb_check = $(shell $(CC) $(ALL_CFLAGS) \
+ -c -MJ /dev/null \
+ -x c /dev/null -o /dev/null 2>&1; \
+ echo $$?)
+ifeq ($(compdb_check),0)
+override GENERATE_COMPILATION_DATABASE = yes
+else
+override GENERATE_COMPILATION_DATABASE = no
+$(warning GENERATE_COMPILATION_DATABASE is set, but your compiler does not \
+support generating compilation database entries)
+endif
+endif
+
ifdef SANE_TOOL_PATH
SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix "$(SANE_TOOL_PATH_SQ)"|'
@@ -2381,16 +2401,30 @@ missing_dep_dirs =
dep_args =
endif
+compdb_dir = compile_commands/
+
+ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
+missing_compdb_dir = $(compdb_dir)
+$(missing_compdb_dir):
+ @mkdir -p $@
+
+compdb_file = $(compdb_dir)$(subst .-,,$(subst /,-,$(dir $@)))$(notdir $@).json
+compdb_args = -MJ $(compdb_file)
+else
+missing_compdb_dir =
+compdb_args =
+endif
+
ASM_SRC := $(wildcard $(OBJECTS:o=S))
ASM_OBJ := $(ASM_SRC:S=o)
C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
.SUFFIXES:
-$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs)
- $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
-$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs)
- $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
+$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
+ $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
+$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) $(missing_compdb_dir)
+ $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(compdb_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
%.s: %.c GIT-CFLAGS FORCE
$(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
@@ -2413,6 +2447,14 @@ else
$(OBJECTS): $(LIB_H) $(GENERATED_H)
endif
+ifeq ($(GENERATE_COMPILATION_DATABASE),yes)
+all:: compile_commands.json
+compile_commands.json:
+ @$(RM) $@
+ $(QUIET_GEN)sed -e '1s/^/[/' -e '$$s/,$$/]/' $(compdb_dir)*.o.json > $@+
+ @if test -s $@+; then mv $@+ $@; else $(RM) $@+; fi
+endif
+
exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
'-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
@@ -3117,7 +3159,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) $(TEST_PROGRAMS)
$(RM) $(FUZZ_PROGRAMS)
$(RM) $(HCC)
- $(RM) -r bin-wrappers $(dep_dirs)
+ $(RM) -r bin-wrappers $(dep_dirs) $(compdb_dir) compile_commands.json
$(RM) -r po/build/
$(RM) *.pyc *.pyo */*.pyc */*.pyo $(GENERATED_H) $(ETAGS_TARGET) tags cscope*
$(RM) -r $(GIT_TARNAME) .doc-tmp-dir
base-commit: d9cd4331470f4d9d78677f12dc79063dab832f53
--
gitgitgadget
^ permalink raw reply related
* [PATCH v3 3/3] wt-status: tolerate dangling marks
From: Jonathan Tan @ 2020-09-01 22:28 UTC (permalink / raw)
To: git; +Cc: Jonathan Tan, gitster
In-Reply-To: <cover.1598998706.git.jonathantanmy@google.com>
When a user checks out the upstream branch of HEAD, the upstream branch
not being a local branch, and then runs "git status", like this:
git clone $URL client
cd client
git checkout @{u}
git status
no status is printed, but instead an error message:
fatal: HEAD does not point to a branch
(This error message when running "git branch" persists even after
checking out other things - it only stops after checking out a branch.)
This is because "git status" reads the reflog when determining the "HEAD
detached" message, and thus attempts to DWIM "@{u}", but that doesn't
work because HEAD no longer points to a branch.
Therefore, when calculating the status of a worktree, tolerate dangling
marks. This is done by adding an additional parameter to
dwim_ref() and repo_dwim_ref().
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
archive.c | 4 ++--
branch.c | 2 +-
builtin/checkout.c | 4 ++--
builtin/fast-export.c | 2 +-
builtin/log.c | 2 +-
builtin/merge.c | 2 +-
builtin/reset.c | 2 +-
builtin/rev-parse.c | 2 +-
builtin/show-branch.c | 2 +-
builtin/stash.c | 2 +-
bundle.c | 2 +-
cache.h | 7 +++++++
commit.c | 2 +-
refs.c | 14 +++++++++-----
refs.h | 8 +++++---
remote.c | 2 +-
sha1-name.c | 16 +++++++++++-----
t/t7508-status.sh | 12 ++++++++++++
wt-status.c | 2 +-
19 files changed, 60 insertions(+), 29 deletions(-)
diff --git a/archive.c b/archive.c
index fb39706120..0de6048bfc 100644
--- a/archive.c
+++ b/archive.c
@@ -397,10 +397,10 @@ static void parse_treeish_arg(const char **argv,
const char *colon = strchrnul(name, ':');
int refnamelen = colon - name;
- if (!dwim_ref(name, refnamelen, &oid, &ref))
+ if (!dwim_ref(name, refnamelen, &oid, &ref, 0))
die(_("no such ref: %.*s"), refnamelen, name);
} else {
- dwim_ref(name, strlen(name), &oid, &ref);
+ dwim_ref(name, strlen(name), &oid, &ref, 0);
}
if (get_oid(name, &oid))
diff --git a/branch.c b/branch.c
index 7095f78058..9c9dae1eae 100644
--- a/branch.c
+++ b/branch.c
@@ -281,7 +281,7 @@ void create_branch(struct repository *r,
die(_("Not a valid object name: '%s'."), start_name);
}
- switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref)) {
+ switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref, 0)) {
case 0:
/* Not branching from any existing branch */
if (explicit_tracking)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index bba64108af..1f10cc93dd 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -651,7 +651,7 @@ static void setup_branch_path(struct branch_info *branch)
* If this is a ref, resolve it; otherwise, look up the OID for our
* expression. Failure here is okay.
*/
- if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname))
+ if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
repo_get_oid_committish(the_repository, branch->name, &branch->oid);
strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
@@ -1345,7 +1345,7 @@ static void die_expecting_a_branch(const struct branch_info *branch_info)
struct object_id oid;
char *to_free;
- if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free) == 1) {
+ if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
const char *ref = to_free;
if (skip_prefix(ref, "refs/tags/", &ref))
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9f37895d4c..1b8fca3ee0 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -943,7 +943,7 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
if (e->flags & UNINTERESTING)
continue;
- if (dwim_ref(e->name, strlen(e->name), &oid, &full_name) != 1)
+ if (dwim_ref(e->name, strlen(e->name), &oid, &full_name, 0) != 1)
continue;
if (refspecs.nr) {
diff --git a/builtin/log.c b/builtin/log.c
index b58f8da09e..4ec7f57cf4 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1061,7 +1061,7 @@ static char *find_branch_name(struct rev_info *rev)
return NULL;
ref = rev->cmdline.rev[positive].name;
tip_oid = &rev->cmdline.rev[positive].item->oid;
- if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref) &&
+ if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
skip_prefix(full_ref, "refs/heads/", &v) &&
oideq(tip_oid, &branch_oid))
branch = xstrdup(v);
diff --git a/builtin/merge.c b/builtin/merge.c
index 74829a838e..2af70b5605 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -500,7 +500,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
if (!remote_head)
die(_("'%s' does not point to a commit"), remote);
- if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref) > 0) {
+ if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref, 0) > 0) {
if (starts_with(found_ref, "refs/heads/")) {
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
oid_to_hex(&branch_head), remote);
diff --git a/builtin/reset.c b/builtin/reset.c
index 8ae69d6f2b..c635b062c3 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -423,7 +423,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
char *ref = NULL;
int err;
- dwim_ref(rev, strlen(rev), &dummy, &ref);
+ dwim_ref(rev, strlen(rev), &dummy, &ref, 0);
if (ref && !starts_with(ref, "refs/"))
ref = NULL;
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 669dd2fd6f..ed200c8af1 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -136,7 +136,7 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
struct object_id discard;
char *full;
- switch (dwim_ref(name, strlen(name), &discard, &full)) {
+ switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
case 0:
/*
* Not found -- not a ref. We could
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 7eae5f3801..d6d2dabeca 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -741,7 +741,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
die(Q_("only %d entry can be shown at one time.",
"only %d entries can be shown at one time.",
MAX_REVS), MAX_REVS);
- if (!dwim_ref(*av, strlen(*av), &oid, &ref))
+ if (!dwim_ref(*av, strlen(*av), &oid, &ref, 0))
die(_("no such ref %s"), *av);
/* Has the base been specified? */
diff --git a/builtin/stash.c b/builtin/stash.c
index 4bdfaf8397..3f811f3050 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -185,7 +185,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
end_of_rev = strchrnul(revision, '@');
strbuf_add(&symbolic, revision, end_of_rev - revision);
- ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
+ ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
strbuf_release(&symbolic);
switch (ret) {
case 0: /* Not found, but valid ref */
diff --git a/bundle.c b/bundle.c
index 995a940dfd..cb0e5931ac 100644
--- a/bundle.c
+++ b/bundle.c
@@ -403,7 +403,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
if (e->item->flags & UNINTERESTING)
continue;
- if (dwim_ref(e->name, strlen(e->name), &oid, &ref) != 1)
+ if (dwim_ref(e->name, strlen(e->name), &oid, &ref, 0) != 1)
goto skip_write_ref;
if (read_ref_full(e->name, RESOLVE_REF_READING, &oid, &flag))
flag = 0;
diff --git a/cache.h b/cache.h
index 4f16a57ba4..cee8aa5dc3 100644
--- a/cache.h
+++ b/cache.h
@@ -1569,6 +1569,13 @@ struct interpret_branch_name_options {
* allowed, even ones to refs outside of those namespaces.
*/
unsigned allowed;
+
+ /*
+ * If ^{upstream} or ^{push} (or equivalent) is requested, and the
+ * branch in question does not have such a reference, return -1 instead
+ * of die()-ing.
+ */
+ unsigned nonfatal_dangling_mark : 1;
};
int repo_interpret_branch_name(struct repository *r,
const char *str, int len,
diff --git a/commit.c b/commit.c
index 4ce8cb38d5..119892abbc 100644
--- a/commit.c
+++ b/commit.c
@@ -921,7 +921,7 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
struct commit *ret = NULL;
char *full_refname;
- switch (dwim_ref(refname, strlen(refname), &oid, &full_refname)) {
+ switch (dwim_ref(refname, strlen(refname), &oid, &full_refname, 0)) {
case 0:
die("No such ref: '%s'", refname);
case 1:
diff --git a/refs.c b/refs.c
index 0fa6067340..e06ee22a8a 100644
--- a/refs.c
+++ b/refs.c
@@ -598,10 +598,13 @@ const char *git_default_branch_name(void)
* to name a branch.
*/
static char *substitute_branch_name(struct repository *r,
- const char **string, int *len)
+ const char **string, int *len,
+ int nonfatal_dangling_mark)
{
struct strbuf buf = STRBUF_INIT;
- struct interpret_branch_name_options options = { 0 } ;
+ struct interpret_branch_name_options options = {
+ .nonfatal_dangling_mark = nonfatal_dangling_mark
+ };
int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
if (ret == *len) {
@@ -615,9 +618,10 @@ static char *substitute_branch_name(struct repository *r,
}
int repo_dwim_ref(struct repository *r, const char *str, int len,
- struct object_id *oid, char **ref)
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark)
{
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len,
+ nonfatal_dangling_mark);
int refs_found = expand_ref(r, str, len, oid, ref);
free(last_branch);
return refs_found;
@@ -661,7 +665,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
struct object_id *oid, char **log)
{
struct ref_store *refs = get_main_ref_store(r);
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len, 0);
const char **p;
int logs_found = 0;
struct strbuf path = STRBUF_INIT;
diff --git a/refs.h b/refs.h
index 8cbef96a8d..e03c106320 100644
--- a/refs.h
+++ b/refs.h
@@ -151,12 +151,14 @@ struct strvec;
void expand_ref_prefix(struct strvec *prefixes, const char *prefix);
int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
-int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
+int repo_dwim_ref(struct repository *r, const char *str, int len,
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark);
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
static inline int dwim_ref(const char *str, int len, struct object_id *oid,
- char **ref)
+ char **ref, int nonfatal_dangling_mark)
{
- return repo_dwim_ref(the_repository, str, len, oid, ref);
+ return repo_dwim_ref(the_repository, str, len, oid, ref,
+ nonfatal_dangling_mark);
}
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
diff --git a/remote.c b/remote.c
index c5ed74f91c..420150837b 100644
--- a/remote.c
+++ b/remote.c
@@ -1558,7 +1558,7 @@ static void set_merge(struct branch *ret)
strcmp(ret->remote_name, "."))
continue;
if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
- &oid, &ref) == 1)
+ &oid, &ref, 0) == 1)
ret->merge[i]->dst = ref;
else
ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
diff --git a/sha1-name.c b/sha1-name.c
index a7a9de66c4..0b23b86ceb 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -809,7 +809,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
- refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref);
+ refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
if (refs_found > 0) {
warning(warn_msg, len, str);
if (advice_object_name_warning)
@@ -860,11 +860,11 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (!len && reflog_len)
/* allow "@{...}" to mean the current branch reflog */
- refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref);
+ refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
else if (reflog_len)
refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
else
- refs_found = repo_dwim_ref(r, str, len, oid, &real_ref);
+ refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
if (!refs_found)
return -1;
@@ -1496,8 +1496,14 @@ static int interpret_branch_mark(struct repository *r,
branch = branch_get(NULL);
value = get_data(branch, &err);
- if (!value)
- die("%s", err.buf);
+ if (!value) {
+ if (options->nonfatal_dangling_mark) {
+ strbuf_release(&err);
+ return -1;
+ } else {
+ die("%s", err.buf);
+ }
+ }
if (!branch_interpret_allowed(value, options->allowed))
return -1;
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index e81759319f..45e1f6ff68 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -846,6 +846,18 @@ test_expect_success 'status refreshes the index' '
test_cmp expect output
'
+test_expect_success 'status shows detached HEAD properly after checking out non-local upstream branch' '
+ test_when_finished rm -rf upstream downstream actual &&
+
+ test_create_repo upstream &&
+ test_commit -C upstream foo &&
+
+ git clone upstream downstream &&
+ git -C downstream checkout @{u} &&
+ git -C downstream status >actual &&
+ test_i18ngrep "HEAD detached at [0-9a-f]\\+" actual
+'
+
test_expect_success 'setup status submodule summary' '
test_create_repo sm && (
cd sm &&
diff --git a/wt-status.c b/wt-status.c
index 7ce58b8aae..a99b7a0c59 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1569,7 +1569,7 @@ static void wt_status_get_detached_from(struct repository *r,
return;
}
- if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref) == 1 &&
+ if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 &&
/* sha1 is a commit? match without further lookup */
(oideq(&cb.noid, &oid) ||
/* perhaps sha1 is a tag, try to dereference to a commit */
--
2.28.0.402.g5ffc5be6b7-goog
^ permalink raw reply related
* [PATCH v3 2/3] refs: move dwim_ref() to header file
From: Jonathan Tan @ 2020-09-01 22:28 UTC (permalink / raw)
To: git; +Cc: Jonathan Tan, gitster
In-Reply-To: <cover.1598998706.git.jonathantanmy@google.com>
This makes it clear that dwim_ref() is just repo_dwim_ref() without the
first parameter.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
refs.c | 5 -----
refs.h | 8 +++++++-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/refs.c b/refs.c
index cf09cd039f..0fa6067340 100644
--- a/refs.c
+++ b/refs.c
@@ -623,11 +623,6 @@ int repo_dwim_ref(struct repository *r, const char *str, int len,
return refs_found;
}
-int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
-{
- return repo_dwim_ref(the_repository, str, len, oid, ref);
-}
-
int expand_ref(struct repository *repo, const char *str, int len,
struct object_id *oid, char **ref)
{
diff --git a/refs.h b/refs.h
index 29e28124cd..8cbef96a8d 100644
--- a/refs.h
+++ b/refs.h
@@ -1,6 +1,8 @@
#ifndef REFS_H
#define REFS_H
+#include "cache.h"
+
struct object_id;
struct ref_store;
struct repository;
@@ -151,7 +153,11 @@ void expand_ref_prefix(struct strvec *prefixes, const char *prefix);
int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
-int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
+static inline int dwim_ref(const char *str, int len, struct object_id *oid,
+ char **ref)
+{
+ return repo_dwim_ref(the_repository, str, len, oid, ref);
+}
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
/*
--
2.28.0.402.g5ffc5be6b7-goog
^ permalink raw reply related
* [PATCH v3 0/3] Fix for git checkout @{u} (non-local) then git status
From: Jonathan Tan @ 2020-09-01 22:28 UTC (permalink / raw)
To: git; +Cc: Jonathan Tan, gitster
In-Reply-To: <20200513004058.34456-1-jonathantanmy@google.com>
Junio writes [1]:
> I even wonder why dwim_ref() is not defined like so in a header:
>
> #define dwim_ref(s, l, o, r) \
> repo_dwim_ref(the_repository, (s), (l), (o), (r))
>
> Which would force a change like the one we are discussing to keep
> them in parallel and keep the promise that only difference between
> the two is that dwim_ref() works with the_repository and the other
> can take an arbitrary repository. Perhaps that can be a preliminary
> clean-up patch before these two patches ;-)
OK done - that's patch 2 here. (I used "static inline" instead of a
preprocessor #define because I prefer not to use the preprocessor whenever
possible, but switching to #define is fine too.)
> Reducing the size of the diff is a good justification only when the
> end result is the same. If it burdens future developers more, that
> is "I write less at the expense of forcing others to write more",
> which is not quite the same thing.
OK - that makes sense.
[1] https://lore.kernel.org/git/xmqqzh6ag1ih.fsf@gitster.c.googlers.com/
Jonathan Tan (3):
sha1-name: replace unsigned int with option struct
refs: move dwim_ref() to header file
wt-status: tolerate dangling marks
archive.c | 4 ++--
branch.c | 2 +-
builtin/checkout.c | 4 ++--
builtin/fast-export.c | 2 +-
builtin/log.c | 2 +-
builtin/merge.c | 2 +-
builtin/reset.c | 2 +-
builtin/rev-parse.c | 2 +-
builtin/show-branch.c | 2 +-
builtin/stash.c | 2 +-
bundle.c | 2 +-
cache.h | 27 ++++++++++++++++++--------
commit.c | 2 +-
refs.c | 20 +++++++++----------
refs.h | 12 ++++++++++--
remote.c | 2 +-
revision.c | 3 ++-
sha1-name.c | 45 ++++++++++++++++++++++++++++---------------
t/t7508-status.sh | 12 ++++++++++++
wt-status.c | 2 +-
20 files changed, 98 insertions(+), 53 deletions(-)
Range-diff against v2:
-: ---------- > 1: 6b3e3077e6 refs: move dwim_ref() to header file
1: 59b91a206d ! 2: 8f489d9633 wt-status: tolerate dangling marks
@@ Commit message
Therefore, when calculating the status of a worktree, tolerate dangling
marks. This is done by adding an additional parameter to
- repo_dwim_ref().
+ dwim_ref() and repo_dwim_ref().
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
+ ## archive.c ##
+@@ archive.c: static void parse_treeish_arg(const char **argv,
+ const char *colon = strchrnul(name, ':');
+ int refnamelen = colon - name;
+
+- if (!dwim_ref(name, refnamelen, &oid, &ref))
++ if (!dwim_ref(name, refnamelen, &oid, &ref, 0))
+ die(_("no such ref: %.*s"), refnamelen, name);
+ } else {
+- dwim_ref(name, strlen(name), &oid, &ref);
++ dwim_ref(name, strlen(name), &oid, &ref, 0);
+ }
+
+ if (get_oid(name, &oid))
+
+ ## branch.c ##
+@@ branch.c: void create_branch(struct repository *r,
+ die(_("Not a valid object name: '%s'."), start_name);
+ }
+
+- switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref)) {
++ switch (dwim_ref(start_name, strlen(start_name), &oid, &real_ref, 0)) {
+ case 0:
+ /* Not branching from any existing branch */
+ if (explicit_tracking)
+
+ ## builtin/checkout.c ##
+@@ builtin/checkout.c: static void setup_branch_path(struct branch_info *branch)
+ * If this is a ref, resolve it; otherwise, look up the OID for our
+ * expression. Failure here is okay.
+ */
+- if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname))
++ if (!dwim_ref(branch->name, strlen(branch->name), &branch->oid, &branch->refname, 0))
+ repo_get_oid_committish(the_repository, branch->name, &branch->oid);
+
+ strbuf_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL);
+@@ builtin/checkout.c: static void die_expecting_a_branch(const struct branch_info *branch_info)
+ struct object_id oid;
+ char *to_free;
+
+- if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free) == 1) {
++ if (dwim_ref(branch_info->name, strlen(branch_info->name), &oid, &to_free, 0) == 1) {
+ const char *ref = to_free;
+
+ if (skip_prefix(ref, "refs/tags/", &ref))
+
+ ## builtin/fast-export.c ##
+@@ builtin/fast-export.c: static void get_tags_and_duplicates(struct rev_cmdline_info *info)
+ if (e->flags & UNINTERESTING)
+ continue;
+
+- if (dwim_ref(e->name, strlen(e->name), &oid, &full_name) != 1)
++ if (dwim_ref(e->name, strlen(e->name), &oid, &full_name, 0) != 1)
+ continue;
+
+ if (refspecs.nr) {
+
+ ## builtin/log.c ##
+@@ builtin/log.c: static char *find_branch_name(struct rev_info *rev)
+ return NULL;
+ ref = rev->cmdline.rev[positive].name;
+ tip_oid = &rev->cmdline.rev[positive].item->oid;
+- if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref) &&
++ if (dwim_ref(ref, strlen(ref), &branch_oid, &full_ref, 0) &&
+ skip_prefix(full_ref, "refs/heads/", &v) &&
+ oideq(tip_oid, &branch_oid))
+ branch = xstrdup(v);
+
+ ## builtin/merge.c ##
+@@ builtin/merge.c: static void merge_name(const char *remote, struct strbuf *msg)
+ if (!remote_head)
+ die(_("'%s' does not point to a commit"), remote);
+
+- if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref) > 0) {
++ if (dwim_ref(remote, strlen(remote), &branch_head, &found_ref, 0) > 0) {
+ if (starts_with(found_ref, "refs/heads/")) {
+ strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
+ oid_to_hex(&branch_head), remote);
+
+ ## builtin/reset.c ##
+@@ builtin/reset.c: int cmd_reset(int argc, const char **argv, const char *prefix)
+ char *ref = NULL;
+ int err;
+
+- dwim_ref(rev, strlen(rev), &dummy, &ref);
++ dwim_ref(rev, strlen(rev), &dummy, &ref, 0);
+ if (ref && !starts_with(ref, "refs/"))
+ ref = NULL;
+
+
+ ## builtin/rev-parse.c ##
+@@ builtin/rev-parse.c: static void show_rev(int type, const struct object_id *oid, const char *name)
+ struct object_id discard;
+ char *full;
+
+- switch (dwim_ref(name, strlen(name), &discard, &full)) {
++ switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
+ case 0:
+ /*
+ * Not found -- not a ref. We could
+
+ ## builtin/show-branch.c ##
+@@ builtin/show-branch.c: int cmd_show_branch(int ac, const char **av, const char *prefix)
+ die(Q_("only %d entry can be shown at one time.",
+ "only %d entries can be shown at one time.",
+ MAX_REVS), MAX_REVS);
+- if (!dwim_ref(*av, strlen(*av), &oid, &ref))
++ if (!dwim_ref(*av, strlen(*av), &oid, &ref, 0))
+ die(_("no such ref %s"), *av);
+
+ /* Has the base been specified? */
+
+ ## builtin/stash.c ##
+@@ builtin/stash.c: static int get_stash_info(struct stash_info *info, int argc, const char **argv)
+ end_of_rev = strchrnul(revision, '@');
+ strbuf_add(&symbolic, revision, end_of_rev - revision);
+
+- ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref);
++ ret = dwim_ref(symbolic.buf, symbolic.len, &dummy, &expanded_ref, 0);
+ strbuf_release(&symbolic);
+ switch (ret) {
+ case 0: /* Not found, but valid ref */
+
+ ## bundle.c ##
+@@ bundle.c: static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
+
+ if (e->item->flags & UNINTERESTING)
+ continue;
+- if (dwim_ref(e->name, strlen(e->name), &oid, &ref) != 1)
++ if (dwim_ref(e->name, strlen(e->name), &oid, &ref, 0) != 1)
+ goto skip_write_ref;
+ if (read_ref_full(e->name, RESOLVE_REF_READING, &oid, &flag))
+ flag = 0;
+
## cache.h ##
@@ cache.h: struct interpret_branch_name_options {
* allowed, even ones to refs outside of those namespaces.
@@ cache.h: struct interpret_branch_name_options {
int repo_interpret_branch_name(struct repository *r,
const char *str, int len,
+ ## commit.c ##
+@@ commit.c: struct commit *get_fork_point(const char *refname, struct commit *commit)
+ struct commit *ret = NULL;
+ char *full_refname;
+
+- switch (dwim_ref(refname, strlen(refname), &oid, &full_refname)) {
++ switch (dwim_ref(refname, strlen(refname), &oid, &full_refname, 0)) {
+ case 0:
+ die("No such ref: '%s'", refname);
+ case 1:
+
## refs.c ##
@@ refs.c: const char *git_default_branch_name(void)
* to name a branch.
@@ refs.c: static char *substitute_branch_name(struct repository *r,
int refs_found = expand_ref(r, str, len, oid, ref);
free(last_branch);
return refs_found;
-@@ refs.c: int repo_dwim_ref(struct repository *r, const char *str, int len,
-
- int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
- {
-- return repo_dwim_ref(the_repository, str, len, oid, ref);
-+ return repo_dwim_ref(the_repository, str, len, oid, ref, 0);
- }
-
- int expand_ref(struct repository *repo, const char *str, int len,
@@ refs.c: int repo_dwim_log(struct repository *r, const char *str, int len,
struct object_id *oid, char **log)
{
@@ refs.h: struct strvec;
+int repo_dwim_ref(struct repository *r, const char *str, int len,
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark);
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
- int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
+ static inline int dwim_ref(const char *str, int len, struct object_id *oid,
+- char **ref)
++ char **ref, int nonfatal_dangling_mark)
+ {
+- return repo_dwim_ref(the_repository, str, len, oid, ref);
++ return repo_dwim_ref(the_repository, str, len, oid, ref,
++ nonfatal_dangling_mark);
+ }
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
+
+
+ ## remote.c ##
+@@ remote.c: static void set_merge(struct branch *ret)
+ strcmp(ret->remote_name, "."))
+ continue;
+ if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
+- &oid, &ref) == 1)
++ &oid, &ref, 0) == 1)
+ ret->merge[i]->dst = ref;
+ else
+ ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
## sha1-name.c ##
@@ sha1-name.c: static int get_oid_basic(struct repository *r, const char *str, int len,
@@ wt-status.c: static void wt_status_get_detached_from(struct repository *r,
}
- if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref) == 1 &&
-+ if (repo_dwim_ref(the_repository, cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 &&
++ if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 &&
/* sha1 is a commit? match without further lookup */
(oideq(&cb.noid, &oid) ||
/* perhaps sha1 is a tag, try to dereference to a commit */
--
2.28.0.402.g5ffc5be6b7-goog
^ permalink raw reply
* [PATCH v3 1/3] sha1-name: replace unsigned int with option struct
From: Jonathan Tan @ 2020-09-01 22:28 UTC (permalink / raw)
To: git; +Cc: Jonathan Tan, gitster
In-Reply-To: <cover.1598998706.git.jonathantanmy@google.com>
In preparation for a future patch adding a boolean parameter to
repo_interpret_branch_name(), which might be easily confused with an
existing unsigned int parameter, refactor repo_interpret_branch_name()
to take an option struct instead of the unsigned int parameter.
The static function interpret_branch_mark() is also updated to take the
option struct in preparation for that future patch, since it will also
make use of the to-be-introduced boolean parameter.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
cache.h | 20 ++++++++++++--------
refs.c | 3 ++-
revision.c | 3 ++-
sha1-name.c | 29 ++++++++++++++++++-----------
4 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/cache.h b/cache.h
index 4cad61ffa4..4f16a57ba4 100644
--- a/cache.h
+++ b/cache.h
@@ -1557,21 +1557,25 @@ int parse_oid_hex_any(const char *hex, struct object_id *oid, const char **end);
*
* If the input was ok but there are not N branch switches in the
* reflog, it returns 0.
- *
- * If "allowed" is non-zero, it is a treated as a bitfield of allowable
- * expansions: local branches ("refs/heads/"), remote branches
- * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
- * allowed, even ones to refs outside of those namespaces.
*/
#define INTERPRET_BRANCH_LOCAL (1<<0)
#define INTERPRET_BRANCH_REMOTE (1<<1)
#define INTERPRET_BRANCH_HEAD (1<<2)
+struct interpret_branch_name_options {
+ /*
+ * If "allowed" is non-zero, it is a treated as a bitfield of allowable
+ * expansions: local branches ("refs/heads/"), remote branches
+ * ("refs/remotes/"), or "HEAD". If no "allowed" bits are set, any expansion is
+ * allowed, even ones to refs outside of those namespaces.
+ */
+ unsigned allowed;
+};
int repo_interpret_branch_name(struct repository *r,
const char *str, int len,
struct strbuf *buf,
- unsigned allowed);
-#define interpret_branch_name(str, len, buf, allowed) \
- repo_interpret_branch_name(the_repository, str, len, buf, allowed)
+ const struct interpret_branch_name_options *options);
+#define interpret_branch_name(str, len, buf, options) \
+ repo_interpret_branch_name(the_repository, str, len, buf, options)
int validate_headref(const char *ref);
diff --git a/refs.c b/refs.c
index 3ee3afaf41..cf09cd039f 100644
--- a/refs.c
+++ b/refs.c
@@ -601,7 +601,8 @@ static char *substitute_branch_name(struct repository *r,
const char **string, int *len)
{
struct strbuf buf = STRBUF_INIT;
- int ret = repo_interpret_branch_name(r, *string, *len, &buf, 0);
+ struct interpret_branch_name_options options = { 0 } ;
+ int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
if (ret == *len) {
size_t size;
diff --git a/revision.c b/revision.c
index 96630e3186..1247ee4ec8 100644
--- a/revision.c
+++ b/revision.c
@@ -315,13 +315,14 @@ static void add_pending_object_with_path(struct rev_info *revs,
const char *name, unsigned mode,
const char *path)
{
+ struct interpret_branch_name_options options = { 0 };
if (!obj)
return;
if (revs->no_walk && (obj->flags & UNINTERESTING))
revs->no_walk = 0;
if (revs->reflog_info && obj->type == OBJ_COMMIT) {
struct strbuf buf = STRBUF_INIT;
- int len = interpret_branch_name(name, 0, &buf, 0);
+ int len = interpret_branch_name(name, 0, &buf, &options);
if (0 < len && name[len] && buf.len)
strbuf_addstr(&buf, name + len);
diff --git a/sha1-name.c b/sha1-name.c
index 0b8cb5247a..a7a9de66c4 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -1427,9 +1427,12 @@ static int reinterpret(struct repository *r,
struct strbuf tmp = STRBUF_INIT;
int used = buf->len;
int ret;
+ struct interpret_branch_name_options options = {
+ .allowed = allowed
+ };
strbuf_add(buf, name + len, namelen - len);
- ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, allowed);
+ ret = repo_interpret_branch_name(r, buf->buf, buf->len, &tmp, &options);
/* that data was not interpreted, remove our cruft */
if (ret < 0) {
strbuf_setlen(buf, used);
@@ -1471,7 +1474,7 @@ static int interpret_branch_mark(struct repository *r,
int (*get_mark)(const char *, int),
const char *(*get_data)(struct branch *,
struct strbuf *),
- unsigned allowed)
+ const struct interpret_branch_name_options *options)
{
int len;
struct branch *branch;
@@ -1496,7 +1499,7 @@ static int interpret_branch_mark(struct repository *r,
if (!value)
die("%s", err.buf);
- if (!branch_interpret_allowed(value, allowed))
+ if (!branch_interpret_allowed(value, options->allowed))
return -1;
set_shortened_ref(r, buf, value);
@@ -1506,7 +1509,7 @@ static int interpret_branch_mark(struct repository *r,
int repo_interpret_branch_name(struct repository *r,
const char *name, int namelen,
struct strbuf *buf,
- unsigned allowed)
+ const struct interpret_branch_name_options *options)
{
char *at;
const char *start;
@@ -1515,7 +1518,7 @@ int repo_interpret_branch_name(struct repository *r,
if (!namelen)
namelen = strlen(name);
- if (!allowed || (allowed & INTERPRET_BRANCH_LOCAL)) {
+ if (!options->allowed || (options->allowed & INTERPRET_BRANCH_LOCAL)) {
len = interpret_nth_prior_checkout(r, name, namelen, buf);
if (!len) {
return len; /* syntax Ok, not enough switches */
@@ -1523,7 +1526,8 @@ int repo_interpret_branch_name(struct repository *r,
if (len == namelen)
return len; /* consumed all */
else
- return reinterpret(r, name, namelen, len, buf, allowed);
+ return reinterpret(r, name, namelen, len, buf,
+ options->allowed);
}
}
@@ -1531,22 +1535,22 @@ int repo_interpret_branch_name(struct repository *r,
(at = memchr(start, '@', namelen - (start - name)));
start = at + 1) {
- if (!allowed || (allowed & INTERPRET_BRANCH_HEAD)) {
+ if (!options->allowed || (options->allowed & INTERPRET_BRANCH_HEAD)) {
len = interpret_empty_at(name, namelen, at - name, buf);
if (len > 0)
return reinterpret(r, name, namelen, len, buf,
- allowed);
+ options->allowed);
}
len = interpret_branch_mark(r, name, namelen, at - name, buf,
upstream_mark, branch_get_upstream,
- allowed);
+ options);
if (len > 0)
return len;
len = interpret_branch_mark(r, name, namelen, at - name, buf,
push_mark, branch_get_push,
- allowed);
+ options);
if (len > 0)
return len;
}
@@ -1557,7 +1561,10 @@ int repo_interpret_branch_name(struct repository *r,
void strbuf_branchname(struct strbuf *sb, const char *name, unsigned allowed)
{
int len = strlen(name);
- int used = interpret_branch_name(name, len, sb, allowed);
+ struct interpret_branch_name_options options = {
+ .allowed = allowed
+ };
+ int used = interpret_branch_name(name, len, sb, &options);
if (used < 0)
used = 0;
--
2.28.0.402.g5ffc5be6b7-goog
^ permalink raw reply related
* [Suggestion] Documentation: quick-install-man not propagating DESTDIR
From: Randall S. Becker @ 2020-09-01 22:28 UTC (permalink / raw)
To: 'git'
The make quick-install-man rule is not propagating DESTDIR when GNU Make
4.2.1 is used.
It seems like a bit of a nit to report this, but I discovered that the
installation is not putting the manuals in the same place as git. Its a
pretty simple fix. I can put a patch together if desired.
diff --git a/Makefile b/Makefile
index 372139f1f2..dae2d99a7f 100644
--- a/Makefile
+++ b/Makefile
@@ -2992,10 +2992,10 @@ install-gitweb:
$(MAKE) -C gitweb install
install-doc: install-man-perl
- $(MAKE) -C Documentation install
+ $(MAKE) -C Documentation install DESTDIR=$(DESTDIR)
install-man: install-man-perl
- $(MAKE) -C Documentation install-man
+ $(MAKE) -C Documentation install-man DESTDIR=$(DESTDIR)
install-man-perl: man-perl
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mandir_SQ)/man3'
@@ -3006,19 +3006,19 @@ install-html:
$(MAKE) -C Documentation install-html
install-info:
- $(MAKE) -C Documentation install-info
+ $(MAKE) -C Documentation install-info DESTDIR=$(DESTDIR)
install-pdf:
- $(MAKE) -C Documentation install-pdf
+ $(MAKE) -C Documentation install-pdf DESTDIR=$(DESTDIR)
quick-install-doc:
- $(MAKE) -C Documentation quick-install
+ $(MAKE) -C Documentation quick-install DESTDIR=$(DESTDIR)
quick-install-man:
- $(MAKE) -C Documentation quick-install-man
+ $(MAKE) -C Documentation quick-install-man DESTDIR=$(DESTDIR)
quick-install-html:
- $(MAKE) -C Documentation quick-install-html
+ $(MAKE) -C Documentation quick-install-html DESTDIR=$(DESTDIR)
-- Brief whoami:
NonStop developer since approximately 211288444200000000
UNIX developer since approximately 421664400
-- In my real life, I talk too much.
^ permalink raw reply related
* Re: [PATCH v4 4/6] config: correctly read worktree configs in submodules
From: Matheus Tavares Bernardino @ 2020-09-01 21:44 UTC (permalink / raw)
To: Jonathan Nieder
Cc: git, Junio C Hamano, Derrick Stolee, Elijah Newren, Jonathan Tan
In-Reply-To: <20200901024130.GA3332286@google.com>
Hi, Jonathan
On Mon, Aug 31, 2020 at 11:41 PM Jonathan Nieder <jrnieder@gmail.com> wrote:
>
> Hi,
>
> Matheus Tavares wrote:
>
> > One of the steps in do_git_config_sequence() is to load the
> > worktree-specific config file. Although the function receives a git_dir
> > string, it relies on git_pathdup(), which uses the_repository->git_dir,
> > to make the path to the file. Furthermore, it also checks that
> > extensions.worktreeConfig is set through the
> > repository_format_worktree_config variable, which refers to
> > the_repository only. Thus, when a submodule has worktree-specific
> > settings, a command executed in the superproject that recurses into the
> > submodule won't find the said settings.
>
> I think the above goes out of order: it states the "how" before the
> "what". Instead, a commit message should lead with the problem the
> change aims to solve.
Thanks. I will reorder these two sections in the commit message.
> Is the idea here that until this patch, we're only able to read
> worktree config from a repository when extensions.worktreeConfig is
> set in the_repository, meaning that
>
> - when examining submodule config in a process where the_repository
> represents the superproject, we do not read the submodule's worktree
> config even if extensions.worktreeConfig is set in the submodule,
> unless the superproject has extensions.worktreeConfig set, and
Right.
> - when examining submodule config in a process where the_repository
> represents the superproject, we *do* read the submodule's worktree
> config even if extensions.worktreeConfig is not set in the submodule,
> if the superproject has extensions.worktreeConfig set, and
>
> ?
Right, but with one change: if extensions.worktreeConfig is not set in
the submodule and it is set in the superproject, the *superproject's*
worktree config is read (independently of which git_dir was given as
argument).
> That sounds like a serious problem indeed. Thanks for fixing it.
>
> > This will be especially important in the next patch: git-grep will learn
> > to honor sparse checkouts and, when running with --recurse-submodules,
> > the submodule's sparse checkout settings must be loaded. As these
> > settings are stored in the config.worktree file, they would be ignored
> > without this patch. So let's fix this by reading the right
> > config.worktree file and extensions.worktreeConfig setting, based on the
> > git_dir and commondir paths given to do_git_config_sequence(). Also
> > add a test to avoid any regressions.
>
> I see. I'm not sure that's more important than other cases, but I
> can understand if the problem was noticed in this circumstance. :)
>
> > Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
> > ---
> > config.c | 21 +++++++++---
> > t/helper/test-config.c | 67 +++++++++++++++++++++++++++++++++-----
> > t/t2404-worktree-config.sh | 16 +++++++++
> > 3 files changed, 91 insertions(+), 13 deletions(-)
> >
> > diff --git a/config.c b/config.c
> > index 8db9c77098..c2d56309dc 100644
> > --- a/config.c
> > +++ b/config.c
> > @@ -1747,11 +1747,22 @@ static int do_git_config_sequence(const struct config_options *opts,
> > ret += git_config_from_file(fn, repo_config, data);
> >
> > current_parsing_scope = CONFIG_SCOPE_WORKTREE;
> > - if (!opts->ignore_worktree && repository_format_worktree_config) {
> > + if (!opts->ignore_worktree && repo_config && opts->git_dir) {
>
> Can we eliminate the repository_format_worktree_config global to save
> the next caller from the same problem?
Hmm, I think it's possible, I will investigate it further.
> > + struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
> > + struct strbuf buf = STRBUF_INIT;
> > +
> > + read_repository_format(&repo_fmt, repo_config);
> > +
> > + if (!verify_repository_format(&repo_fmt, &buf) &&
> > + repo_fmt.worktree_config) {
>
> This undoes the caching the repository_format_worktree_config means to
> do. Can we cache the value in "struct repository" instead? That way,
> in the common case where we're reading the_repository, we wouldn't
> experience a slowdown.
Yeah, that would be the best solution. But, unfortunately,
do_git_config_sequence() doesn't receive a complete repository struct,
just the 'commondir' and 'git_dir' strings.
> > - char *path = git_pathdup("config.worktree");
> > + char *path = mkpathdup("%s/config.worktree", opts->git_dir);
>
> Can this use a helper like repo_git_path or strbuf_repo_git_path
> (preferably one using strbuf like the latter)?
Hmm, here we would have the same problem of not having a 'struct
repository' to pass to those functions :(
> [...]
> > + strbuf_release(&buf);
> > + clear_repository_format(&repo_fmt);
> > }
> >
> > current_parsing_scope = CONFIG_SCOPE_COMMAND;
> > diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> > index 61da2574c5..284f83a921 100644
> > --- a/t/helper/test-config.c
> > +++ b/t/helper/test-config.c
> > @@ -2,12 +2,19 @@
> > #include "cache.h"
> > #include "config.h"
> > #include "string-list.h"
> > +#include "submodule-config.h"
> >
> > /*
> > * This program exposes the C API of the configuration mechanism
> > * as a set of simple commands in order to facilitate testing.
> > *
> > - * Reads stdin and prints result of command to stdout:
> > + * Usage: test-tool config [--submodule=<path>] <cmd> [<args>]
> > + *
> > + * If --submodule=<path> is given, <cmd> will operate on the submodule at the
> > + * given <path>. This option is not valid for the commands: read_early_config,
> > + * configset_get_value and configset_get_value_multi.
>
> Nice!
>
> [...]
> > @@ -93,7 +102,18 @@ int cmd__config(int argc, const char **argv)
> > if (argc == 0)
> > goto print_usage_error;
> >
> > + if (skip_prefix(*argv, "--submodule=", &subrepo_path)) {
> > + argc--;
> > + argv++;
> > + if (argc == 0)
> > + goto print_usage_error;
> > + }
>
> Can this use the parse_options API?
Right, it would make it easier to add more options in the future.
There is only one consideration, though, about parse_options()'s exit
codes on error, but more on that below...
> > +
> > if (argc == 2 && !strcmp(argv[0], "read_early_config")) {
> > + if (subrepo_path) {
> > + fprintf(stderr, "Cannot use --submodule with read_early_config\n");
> > + return TC_USAGE_ERROR;
>
> Should this use die() or BUG()?
The idea of using TC_USAGE_ERROR (129) here and not die() (128), was
that some users of the test-config helper want to detect die() errors
from the config machinery itself. So by using a different exit code,
we can avoid false positives in these tests. Of course they should
also be checking stderr/stdout, but there is at least one test which
only checks the exit code. Rethinking about that now, instead of using
different exit codes in test-config.c, should we adjust the tests to
use `test_must_fail` and only check stderr/stdout? Then we could use
die() (or BUG()) here, as you suggested, as well as the parse_options
API in the snippet above. Does that sound reasonable?
> > + }
> > read_early_config(early_config_cb, (void *)argv[1]);
> > return TC_SUCCESS;
> > }
> > @@ -101,8 +121,23 @@ int cmd__config(int argc, const char **argv)
> > setup_git_directory();
> > git_configset_init(&cs);
> >
> > + if (subrepo_path) {
> > + const struct submodule *sub;
> > + struct repository *subrepo = xcalloc(1, sizeof(*repo));
>
> nit: this could be scoped to cmd__config:
>
> struct repository subrepo = {0};
OK, will do. Thanks
> > +
> > + sub = submodule_from_path(the_repository, &null_oid, subrepo_path);
> > + if (!sub || repo_submodule_init(subrepo, the_repository, sub)) {
> > + fprintf(stderr, "Invalid argument to --submodule: '%s'\n",
> > + subrepo_path);
> > + free(subrepo);
> > + ret = TC_USAGE_ERROR;
>
> Likewise: I think may want to use die() or BUG() (and likewise for other
> USAGE_ERROR cases).
>
> Thanks and hope that helps,
> Jonathan
It did :) Thanks a lot for the comments!
^ permalink raw reply
* Re: What's cooking in git.git (Sep 2020, #01; Tue, 1)
From: Eric Sunshine @ 2020-09-01 21:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git List
In-Reply-To: <xmqqblipchk6.fsf@gitster.c.googlers.com>
On Tue, Sep 1, 2020 at 5:30 PM Junio C Hamano <gitster@pobox.com> wrote:
> * jc/run-command-use-embedded-args (2020-08-26) 1 commit
> Various callers of run_command API has been modernized.
s/has/have/
> * es/worktree-repair (2020-08-31) 5 commits
> (merged to 'next' on 2020-08-31 at 604825c5e4)
> + init: make --separate-git-dir work from within linked worktree
> + init: teach --separate-git-dir to repair linked worktrees
> + worktree: teach "repair" to fix outgoing links to worktrees
> + worktree: teach "repair" to fix worktree back-links to main worktree
> + worktree: add skeleton "repair" command
>
> "git worktree repair" command to correct on-disk pointers between
> the repository and its secondary working trees.
I wonder if this could be reworded so it's clearer that "git worktree
repair" is a new command, and to mention fixes to "git init
--separate-git-dir". Perhaps like this?
"git worktree" gained a "repair" subcommand to help users recover
from problems arising from factors outside of Git's control.
Also, "git init --separate-git-dir" no longer corrupts
administrative data related to linked worktrees.
^ permalink raw reply
* What's cooking in git.git (Sep 2020, #01; Tue, 1)
From: Junio C Hamano @ 2020-09-01 21:28 UTC (permalink / raw)
To: git
Here are the topics that have been cooking. Commits prefixed with '-' are
only in 'seen' (formerly 'pu'---proposed updates) while commits prefixed
with '+' are in 'next'. The ones marked with '.' do not appear in any of
the integration branches, but I am still holding onto them.
You can find the changes described here in the integration branches of the
repositories listed at
http://git-blame.blogspot.com/p/git-public-repositories.html
--------------------------------------------------
[Graduated to 'master']
* al/bisect-first-parent (2020-08-22) 1 commit
(merged to 'next' on 2020-08-24 at f95fbf45a6)
+ bisect: add first-parent option to documentation
Finishing touches.
* am/ci-wsfix (2020-08-21) 1 commit
(merged to 'next' on 2020-08-24 at 8491e031f1)
+ ci: fix inconsistent indentation
Aesthetic fix to a CI configuration file.
* dd/diff-customize-index-line-abbrev (2020-08-21) 2 commits
(merged to 'next' on 2020-08-24 at 74e842a2c8)
+ diff: index-line: respect --abbrev in object's name
+ t4013: improve diff-post-processor logic
The output from the "diff" family of the commands had abbreviated
object names of blobs involved in the patch, but its length was not
affected by the --abbrev option. Now it is.
* hn/refs-pseudorefs (2020-08-21) 4 commits
(merged to 'next' on 2020-08-24 at 3579abe8ff)
+ sequencer: treat REVERT_HEAD as a pseudo ref
+ builtin/commit: suggest update-ref for pseudoref removal
+ sequencer: treat CHERRY_PICK_HEAD as a pseudo ref
+ refs: make refs_ref_exists public
Accesses to two pseudorefs have been updated to properly use ref
API.
* hv/ref-filter-trailers-atom-parsing-fix (2020-08-21) 2 commits
(merged to 'next' on 2020-08-24 at 79b27f3263)
+ ref-filter: 'contents:trailers' show error if `:` is missing
+ t6300: unify %(trailers) and %(contents:trailers) tests
The parser for "git for-each-ref --format=..." was too loose when
parsing the "%(trailers...)" atom, and forgot that "trailers" and
"trailers:<modifiers>" are the only two allowed forms, which has
been corrected.
* jc/ident-whose-ident (2020-08-21) 1 commit
(merged to 'next' on 2020-08-27 at caf5149c28)
+ ident: say whose identity is missing when giving user.name hint
Error message update.
* jk/index-pack-w-more-threads (2020-08-21) 3 commits
(merged to 'next' on 2020-08-24 at 18f18a5b66)
+ index-pack: adjust default threading cap
+ p5302: count up to online-cpus for thread tests
+ p5302: disable thread-count parameter tests by default
Long ago, we decided to use 3 threads by default when running the
index-pack task in parallel, which has been adjusted a bit upwards.
* jk/refspecs-cleanup (2020-08-17) 2 commits
(merged to 'next' on 2020-08-24 at 807a080ebf)
+ refspec: make sure stack refspec_item variables are zeroed
+ refspec: fix documentation referring to refspec_item
(this branch is used by jk/refspecs-negative.)
Preliminary code clean-up before introducing "negative refspec".
* jk/rev-input-given-fix (2020-08-26) 1 commit
(merged to 'next' on 2020-08-27 at da291a327c)
+ revision: set rev_input_given in handle_revision_arg()
Feeding "$ZERO_OID" to "git log --ignore-missing --stdin", and
running "git log --ignore-missing $ZERO_OID" fell back to start
digging from HEAD; it has been corrected to become a no-op, like
"git log --tags=no-tag-matches-this-pattern" does.
* jt/promisor-pack-fix (2020-08-20) 1 commit
(merged to 'next' on 2020-08-24 at cd26d30d8d)
+ fetch-pack: in partial clone, pass --promisor
Updates into a lazy/partial clone with a submodule did not work
well with transfer.fsckobjects set.
* ps/ref-transaction-hook (2020-08-25) 1 commit
(merged to 'next' on 2020-08-27 at 49b3fb8349)
+ refs: remove lookup cache for reference-transaction hook
Code simplification by removing ineffective optimization.
* rp/apply-cached-doc (2020-08-20) 1 commit
(merged to 'next' on 2020-08-27 at 1d610f08ea)
+ git-apply.txt: update descriptions of --cached, --index
The description of --cached/--index options in "git apply --help"
has been updated.
* rs/checkout-no-overlay-pathspec-fix (2020-08-22) 1 commit
(merged to 'next' on 2020-08-27 at 277e39346d)
+ checkout, restore: make pathspec recursive
"git restore/checkout --no-overlay" with wildcarded pathspec
mistakenly removed matching paths in subdirectories, which has been
corrected.
--------------------------------------------------
[New Topics]
* hl/bisect-doc-clarify-bad-good-ordering (2020-08-28) 1 commit
(merged to 'next' on 2020-08-31 at 11ce613916)
+ bisect: swap command-line options in documentation
Doc update.
Will merge to 'master'.
* jc/post-checkout-doc (2020-08-27) 1 commit
- doc: clarify how exit status of post-checkout hook is used
Doc update.
Will merge to 'next'.
* jt/interpret-branch-name-fallback (2020-08-29) 2 commits
(merged to 'next' on 2020-08-31 at 01f5dc8cc0)
+ wt-status: tolerate dangling marks
+ sha1-name: replace unsigned int with option struct
"git status" has trouble showing where it came from by interpreting
reflog entries that recordcertain events, e.g. "checkout @{u}", and
gives a hard/fatal error. Even though it inherently is impossible
to give a correct answer because the reflog entries lose some
information (e.g. "@{u}" does not record what branch the user was
on hence which branch 'the upstream' needs to be computed, and even
if the record were available, the relationship between branches may
have changed), at least hide the error to allow "status" show its
output.
Will merge to 'master'.
* pb/doc-sequence-editor-configuration (2020-08-31) 1 commit
(merged to 'next' on 2020-08-31 at 506466270c)
+ doc: mention GIT_SEQUENCE_EDITOR and 'sequence.editor' more
Doc update.
Will merge to 'master'.
* pb/imap-send-updates (2020-08-31) 3 commits
- git-imap-send.txt: add note about localized Gmail folders
- git-imap-send.txt: do verify SSL certificate for gmail.com
- git-imap-send.txt: don't duplicate 'Examples' sections
"git imap-send" updates.
Will merge to 'next'.
* so/separate-field-for-m-and-diff-merges (2020-08-31) 1 commit
(merged to 'next' on 2020-08-31 at 8def2984ca)
+ revision: add separate field for "-m" of "diff-index -m"
Internal API clean-up to handle two options "diff-index" and "log"
have, which happen to share the same short form, more sensibly.
Will merge to 'master'.
* vv/send-email-with-less-secure-apps-access (2020-08-29) 1 commit
- Documentation/git-send-email.txt: Mention less secure app access might need to enable.
Doc update.
Expecting a reroll.
cf. <xmqqwo1hi9nv.fsf@gitster.c.googlers.com>
cf. <xmqqft85i72s.fsf@gitster.c.googlers.com>
* ew/decline-core-abbrev (2020-09-01) 1 commit
- core.abbrev <off|false|no> disables abbreviations
Allow the configuration to specify no abbreviation regardless of
the hash algorithm.
Expecting a reroll. The intent is very good.
* jk/xrealloc-avoid-use-after-free (2020-09-01) 1 commit
- xrealloc: do not reuse pointer freed by zero-length realloc()
It was possible for xrealloc() to send a non-NULL pointer that has
been freed, which has been fixed.
Expecting a reroll.
* pb/doc-external-diff-env (2020-09-01) 1 commit
- git.txt: correct stale 'GIT_EXTERNAL_DIFF' description
Doc update.
Will merge to 'next'.
--------------------------------------------------
[Stalled]
* jc/war-on-dashed-git (2020-08-27) 1 commit
- git: catch an attempt to run "git-foo"
(this branch uses jc/undash-in-tree-git-callers.)
The first step to remove on-disk binaries for built-in subcommands
by soliciting objections.
On hold for now.
* tb/bloom-improvements (2020-08-11) 14 commits
- builtin/commit-graph.c: introduce '--max-new-filters=<n>'
- commit-graph: rename 'split_commit_graph_opts'
- commit-graph: add large-filters bitmap chunk
- commit-graph.c: sort index into commits list
- bloom/diff: properly short-circuit on max_changes
- bloom: use provided 'struct bloom_filter_settings'
- csum-file.h: introduce 'hashwrite_be64()'
- bloom: split 'get_bloom_filter()' in two
- commit-graph.c: store maximum changed paths
- commit-graph: respect 'commitGraph.readChangedPaths'
- t/helper/test-read-graph.c: prepare repo settings
- commit-graph: pass a 'struct repository *' in more places
- t4216: use an '&&'-chain
- commit-graph: introduce 'get_bloom_filter_settings()'
Misc Bloom filter improvements.
Expecting a reroll.
It seems that the review is getting closer to result in another update.
cf. <20200811220503.GC66656@syl.lan>
* es/config-hooks (2020-07-30) 6 commits
- hook: add 'run' subcommand
- parse-options: parse into argv_array
- hook: add --porcelain to list command
- hook: add list command
- hook: scaffolding for git-hook subcommand
- doc: propose hooks managed by the config
The "hooks defined in config" topic.
Expecting a reroll.
Now jk/strvec is in 'master', we may want to see the topic reworked
on top of it. Are there unresolved issues, or does the topic need
a round of detailed review?
cf. <xmqqmu3i9kvg.fsf@gitster.c.googlers.com>
* mt/grep-sparse-checkout (2020-06-12) 6 commits
- config: add setting to ignore sparsity patterns in some cmds
- grep: honor sparse checkout patterns
- config: correctly read worktree configs in submodules
- t/helper/test-config: facilitate addition of new cli options
- t/helper/test-config: return exit codes consistently
- doc: grep: unify info on configuration variables
"git grep" has been tweaked to be limited to the sparse checkout
paths.
Review needed on 4/6; otherwise looking sane.
cf. <CABPp-BGdEyEeajYZj_rdxp=MyEQdszuyjVTax=hhYj3fOtRQUQ@mail.gmail.com>
* ls/mergetool-meld-auto-merge (2020-07-12) 2 commits
- SQUASH???
- Support auto-merge for meld to follow the vim-diff behavior
The 'meld' backend of the "git mergetool" learned to give the
underlying 'meld' the '--auto-merge' option, which would help
reduce the amount of text that requires manual merging.
Expecting a reroll.
* mf/submodule-summary-with-correct-repository (2020-06-24) 2 commits
- submodule: use submodule repository when preparing summary
- revision: use repository from rev_info when parsing commits
"git diff/show" on a change that involves a submodule used to read
the information on commits in the submodule from a wrong repository
and gave a wrong information when the commit-graph is involved.
Needs tests.
* dr/push-remoteref-fix (2020-04-23) 1 commit
- remote.c: fix handling of %(push:remoteref)
The "%(push:remoteref)" placeholder in the "--format=" argument of
"git format-patch" (and friends) only showed what got explicitly
configured, not what ref at the receiving end would be updated when
"git push" was used, as it ignored the default behaviour (e.g. update
the same ref as the source).
Expecting a reroll.
cf. <20200416152145.wp2zeibxmuyas6y6@feanor>
* mk/use-size-t-in-zlib (2018-10-15) 1 commit
- zlib.c: use size_t for size
The wrapper to call into zlib followed our long tradition to use
"unsigned long" for sizes of regions in memory, which have been
updated to use "size_t".
--------------------------------------------------
[Cooking]
* mr/bisect-in-c-2 (2020-08-31) 13 commits
- bisect--helper: retire `--bisect-autostart` subcommand
- bisect--helper: retire `--write-terms` subcommand
- bisect--helper: retire `--check-expected-revs` subcommand
- bisect--helper: reimplement `bisect_state` & `bisect_head` shell functions in C
- bisect--helper: retire `--next-all` subcommand
- bisect--helper: retire `--bisect-clean-state` subcommand
- bisect--helper: finish porting `bisect_start()` to C
- bisect--helper: reimplement `bisect_next` and `bisect_auto_next` shell functions in C
- bisect: call 'clear_commit_marks_all()' in 'bisect_next_all()'
- bisect--helper: reimplement `bisect_autostart` shell function in C
- bisect--helper: introduce new `write_in_file()` function
- bisect--helper: use '-res' in 'cmd_bisect__helper' return
- bisect--helper: BUG() in cmd_*() on invalid subcommand
Rewrite of the "git bisect" script in C continues.
* jc/undash-in-tree-git-callers (2020-08-27) 3 commits
(merged to 'next' on 2020-08-27 at 671fa2f87e)
+ credential-cache: use child_process.args
+ cvsexportcommit: do not run git programs in dashed form
+ transport-helper: do not run git-remote-ext etc. in dashed form
(this branch is used by jc/war-on-dashed-git.)
A handful of places in in-tree code still relied on being able to
execute the git subcommands, especially built-ins, in "git-foo"
form, which have been corrected.
Will merge to 'master'.
* tb/repack-clearing-midx (2020-08-28) 2 commits
(merged to 'next' on 2020-08-28 at 4204c0cb5e)
+ midx: traverse the local MIDX first
(merged to 'next' on 2020-08-27 at a465875cbb)
+ builtin/repack.c: invalidate MIDX only when necessary
When a packfile is removed by "git repack", multi-pack-index gets
cleared; the code was taught to do so less aggressively by first
checking if the midx actually refers to a pack that no longer
exists.
Will merge to 'master'.
* jc/run-command-use-embedded-args (2020-08-26) 1 commit
(merged to 'next' on 2020-08-27 at c2b688e8e9)
+ run_command: teach API users to use embedded 'args' more
Various callers of run_command API has been modernized.
Will merge to 'master'.
* es/worktree-repair (2020-08-31) 5 commits
(merged to 'next' on 2020-08-31 at 604825c5e4)
+ init: make --separate-git-dir work from within linked worktree
+ init: teach --separate-git-dir to repair linked worktrees
+ worktree: teach "repair" to fix outgoing links to worktrees
+ worktree: teach "repair" to fix worktree back-links to main worktree
+ worktree: add skeleton "repair" command
"git worktree repair" command to correct on-disk pointers between
the repository and its secondary working trees.
Will merge to 'master'.
* jk/worktree-check-clean-leakfix (2020-08-27) 1 commit
(merged to 'next' on 2020-08-31 at 220fc43629)
+ worktree: fix leak in check_clean_worktree()
Leakfix.
Will merge to 'master'.
* so/pretty-abbrev-doc (2020-08-27) 1 commit
(merged to 'next' on 2020-08-31 at d664bd0c06)
+ pretty-options.txt: fix --no-abbrev-commit description
Documentation update for "--no-abbrev-commit".
Will merge to 'master'.
* ss/submodule-summary-in-c-fixes (2020-08-27) 3 commits
- t7421: eliminate 'grep' check in t7421.4 for mingw compatibility
- submodule: fix style in function definition
- submodule: eliminate unused parameters from print_submodule_summary()
(this branch uses ss/submodule-summary-in-c.)
Fixups to a topic in 'next'.
Will merge to 'next'.
* js/no-builtins-on-disk-option (2020-08-24) 3 commits
- ci: stop linking built-ins to the dashed versions
- install: optionally skip linking/copying the built-ins
- msvc: copy the correct `.pdb` files in the Makefile target `install`
The installation procedure learned to optionally omit "git-foo"
executable files for each 'foo' built-in subcommand, which are only
required by old timers that still rely on the age old promise that
prepending "git --exec-path" output to PATH early in their script
will keep the "git-foo" calls they wrote working.
The old attempt to remove these executables from the disk failed in
the 1.6 era; it may be worth attempting again, but I think it is
worth to keep this topic separate from such a policy change to help
it graduate early.
cf. https://public-inbox.org/git/7vprnzt7d5.fsf@gitster.siamese.dyndns.org/
* jt/threaded-index-pack (2020-08-27) 9 commits
- builtin/index-pack.c: fix some sparse warnings
- fixup! index-pack: make quantum of work smaller
- index-pack: make quantum of work smaller
- index-pack: make resolve_delta() assume base data
- index-pack: calculate {ref,ofs}_{first,last} early
- index-pack: remove redundant child field
- index-pack: unify threaded and unthreaded code
- index-pack: remove redundant parameter
- Documentation: deltaBaseCacheLimit is per-thread
"git index-pack" learned to resolve deltified objects with greater
parallelism.
Expecting the final reroll.
cf. https://colabti.org/irclogger/irclogger_log/git-devel?date=2020-08-31#l82
* hv/ref-filter-misc (2020-08-28) 8 commits
- ref-filter: add `sanitize` option for 'subject' atom
- pretty: refactor `format_sanitized_subject()`
- ref-filter: add `short` modifier to 'parent' atom
- ref-filter: add `short` modifier to 'tree' atom
- ref-filter: rename `objectname` related functions and fields
- ref-filter: modify error messages in `grab_objectname()`
- ref-filter: refactor `grab_objectname()`
- ref-filter: support different email formats
The "--format=" option to the "for-each-ref" command and friends
learned a few more tricks, e.g. the ":short" suffix that applies to
"objectname" now also can be used for "parent", "tree", etc.
Will merge to 'next'.
* jk/refspecs-negative (2020-08-21) 1 commit
- refspec: add support for negative refspecs
"negative refspecs"
* jt/fetch-pack-loosen-validation-with-packfile-uri (2020-08-24) 3 commits
(merged to 'next' on 2020-08-27 at efd171f172)
+ fetch-pack: make packfile URIs work with transfer.fsckobjects
+ fetch-pack: document only_packfile in get_pack()
+ (various): document from_promisor parameter
Bugfix for "git fetch" when the packfile URI capability is in use.
Will merge to 'master'.
* mr/diff-hide-stat-wo-textual-change (2020-08-19) 1 commit
(merged to 'next' on 2020-08-27 at b9e97254ae)
+ diff: teach --stat to ignore uninteresting modifications
"git diff --stat -w" showed 0-line changes for paths whose changes
were only whitespaces, which was not intuitive. We now omit such
paths from the stat output.
Will merge to 'master'.
* pw/add-p-allowed-options-fix (2020-08-17) 2 commits
(merged to 'next' on 2020-08-27 at 6cd62753f7)
+ add -p: fix checking of user input
+ add -p: use ALLOC_GROW_BY instead of ALLOW_GROW
"git add -p" update.
Will merge to 'master'.
* jt/lazy-fetch (2020-08-18) 7 commits
(merged to 'next' on 2020-08-27 at 85f2319ba1)
+ fetch-pack: remove no_dependents code
+ promisor-remote: lazy-fetch objects in subprocess
+ fetch-pack: do not lazy-fetch during ref iteration
+ fetch: only populate existing_refs if needed
+ fetch: avoid reading submodule config until needed
+ fetch: allow refspecs specified through stdin
+ negotiator/noop: add noop fetch negotiator
Updates to on-demand fetching code in lazily cloned repositories.
Will merge to 'master'.
* jx/proc-receive-hook (2020-08-27) 10 commits
- doc: add documentation for the proc-receive hook
- transport: parse report options for tracking refs
- t5411: test updates of remote-tracking branches
- receive-pack: new config receive.procReceiveRefs
- doc: add document for capability report-status-v2
- New capability "report-status-v2" for git-push
- receive-pack: feed report options to post-receive
- receive-pack: add new proc-receive hook
- t5411: add basic test cases for proc-receive hook
- transport: not report a non-head push as a branch
"git receive-pack" that accepts requests by "git push" learned to
outsource most of the ref updates to the new "proc-receive" hook.
Looking good.
* pw/rebase-i-more-options (2020-08-26) 6 commits
(merged to 'next' on 2020-08-27 at c55cfeb247)
+ t3436: do not run git-merge-recursive in dashed form
(merged to 'next' on 2020-08-21 at ade71fd49b)
+ rebase: add --reset-author-date
+ rebase -i: support --ignore-date
+ rebase -i: support --committer-date-is-author-date
+ am: stop exporting GIT_COMMITTER_DATE
+ rebase -i: add --ignore-whitespace flag
"git rebase -i" learns a bit more options.
Will merge to 'master'.
* jk/slimmed-down (2020-08-13) 5 commits
(merged to 'next' on 2020-08-27 at bc8e9450c6)
+ drop vcs-svn experiment
+ make git-fast-import a builtin
+ make git-bugreport a builtin
+ make credential helpers builtins
+ Makefile: drop builtins from MSVC pdb list
Trim an unused binary and turn a bunch of commands into built-in.
Will merge to 'master'.
* ss/t7401-modernize (2020-08-21) 5 commits
(merged to 'next' on 2020-08-27 at 516cba9c64)
+ t7401: add a NEEDSWORK
+ t7401: change indentation for enhanced readability
+ t7401: change syntax of test_i18ncmp calls for clarity
+ t7401: use 'short' instead of 'verify' and cut in rev-parse calls
+ t7401: modernize style
Test clean-up.
Will merge to 'master'.
* ds/maintenance-part-2 (2020-08-25) 8 commits
- maintenance: add incremental-repack auto condition
- maintenance: auto-size incremental-repack batch
- maintenance: add incremental-repack task
- midx: use start_delayed_progress()
- midx: enable core.multiPackIndex by default
- maintenance: create auto condition for loose-objects
- maintenance: add loose-objects task
- maintenance: add prefetch task
(this branch uses ds/maintenance-part-1.)
"git maintenance", an extended big brother of "git gc", continues
to evolve.
* ss/submodule-summary-in-c (2020-08-12) 4 commits
(merged to 'next' on 2020-08-17 at 9bc352cb70)
+ submodule: port submodule subcommand 'summary' from shell to C
+ t7421: introduce a test script for verifying 'summary' output
+ submodule: rename helper functions to avoid ambiguity
+ submodule: remove extra line feeds between callback struct and macro
(this branch is used by ss/submodule-summary-in-c-fixes.)
Yet another subcommand of "git submodule" is getting rewritten in C.
Will merge to 'master'.
* ds/maintenance-part-1 (2020-08-25) 11 commits
- maintenance: add trace2 regions for task execution
- maintenance: add auto condition for commit-graph task
- maintenance: use pointers to check --auto
- maintenance: create maintenance.<task>.enabled config
- maintenance: take a lock on the objects directory
- maintenance: add --task option
- maintenance: add commit-graph task
- maintenance: initialize task array
- maintenance: replace run_auto_gc()
- maintenance: add --quiet option
- maintenance: create basic maintenance runner
(this branch is used by ds/maintenance-part-2.)
A "git gc"'s big brother has been introduced to take care of more
repository maintenance tasks, not limited to the object database
cleaning.
Almost ready for 'next'.
cf. https://colabti.org/irclogger/irclogger_log/git-devel?date=2020-08-31#l44
--------------------------------------------------
[Discarded]
* jc/remove-pack-redundant (2020-08-25) 1 commit
- pack-redundant: gauge the usage before proposing its removal
The first step to remove "git pack-redundant" by soliciting
objections.
Stop--we had some activity as late as last year.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox