* Re: [PATCH] diff: add support for reading files literally with --no-index
From: Johannes Schindelin @ 2018-12-21 11:52 UTC (permalink / raw)
To: brian m. carlson; +Cc: git, Jeff King, Duy Nguyen
In-Reply-To: <20181220002610.43832-1-sandals@crustytoothpaste.net>
Hi Brian,
On Thu, 20 Dec 2018, brian m. carlson wrote:
> In some shells, such as bash and zsh, it's possible to use a command
> substitution to provide the output of a command as a file argument to
> another process, like so:
>
> diff -u <(printf "a\nb\n") <(printf "a\nc\n")
>
> However, this syntax does not produce useful results with git diff
> --no-index.
>
> On macOS, the arguments to the command are named pipes under /dev/fd,
> and git diff doesn't know how to handle a named pipe. On Linux, the
> arguments are symlinks to pipes, so git diff "helpfully" diffs these
> symlinks, comparing their targets like "pipe:[1234]" and "pipe:[5678]".
... and in Git for Windows' Bash, it would result in something like:
$ git -P diff --no-index <(printf "a\nb\n") <(printf "a\nc\n")
error: Could not access '/proc/24012/fd/63'
... because the Bash is "MSYS2-aware" and knows about `/proc/` while
`git.exe` is a pure Win32 executable that has no idea what Bash is talking
about.
Sadly, your patch does not change the situation one bit (because it does
not change the fact that the MSYS2 Bash passes a path to `git.exe` that is
not a valid Windows path, and neither could it, but that's not the problem
of your patch).
I reviewed your patch and it looks good to me!
Thanks,
Dscho
> Because this behavior is not very helpful, and because git diff has many
> features that people would like to use even on non-Git files, add an
> option to git diff --no-index to read files literally, dereferencing
> symlinks and reading them as a normal file.
>
> Note that this behavior requires that the files be read entirely into
> memory, just as we do when reading from standard input.
>
> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
> ---
> This is a long-standing annoyance of mine, and it also makes some use
> cases possible (for example, diffing filtered and non-filtered objects).
>
> We don't include a test for the pipe scenario because I couldn't get
> that case to work in portable shell (although of course it works in
> bash). I have, however, tested it on both macOS and Linux. No clue how
> this works on Windows.
>
> Documentation/git-diff.txt | 5 +++++
> diff-no-index.c | 34 +++++++++++++++++++++++++++-------
> diff.c | 24 +++++++++++++-----------
> diff.h | 1 +
> diffcore.h | 1 +
> t/t4053-diff-no-index.sh | 28 ++++++++++++++++++++++++++++
> 6 files changed, 75 insertions(+), 18 deletions(-)
>
> diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
> index 030f162f30..4c4695c88d 100644
> --- a/Documentation/git-diff.txt
> +++ b/Documentation/git-diff.txt
> @@ -111,6 +111,11 @@ include::diff-options.txt[]
> "Unmerged". Can be used only when comparing the working tree
> with the index.
>
> +--literally::
> + Read the specified files literally, as `diff` would,
> + dereferencing any symlinks and reading data from pipes.
> + This option only works with `--no-index`.
> +
> <path>...::
> The <paths> parameters, when given, are used to limit
> the diff to the named paths (you can give directory
> diff --git a/diff-no-index.c b/diff-no-index.c
> index 9414e922d1..2707206aee 100644
> --- a/diff-no-index.c
> +++ b/diff-no-index.c
> @@ -75,7 +75,25 @@ static int populate_from_stdin(struct diff_filespec *s)
> return 0;
> }
>
> -static struct diff_filespec *noindex_filespec(const char *name, int mode)
> +static int populate_literally(struct diff_filespec *s)
> +{
> + struct strbuf buf = STRBUF_INIT;
> + size_t size = 0;
> + int fd = xopen(s->path, O_RDONLY);
> +
> + if (strbuf_read(&buf, fd, 0) < 0)
> + return error_errno("error while reading from '%s'", s->path);
> +
> + s->should_munmap = 0;
> + s->data = strbuf_detach(&buf, &size);
> + s->size = size;
> + s->should_free = 1;
> + s->read_literally = 1;
> + return 0;
> +}
> +
> +static struct diff_filespec *noindex_filespec(const char *name, int mode,
> + struct diff_options *o)
> {
> struct diff_filespec *s;
>
> @@ -85,6 +103,8 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode)
> fill_filespec(s, &null_oid, 0, mode);
> if (name == file_from_standard_input)
> populate_from_stdin(s);
> + else if (o->flags.read_literally)
> + populate_literally(s);
> return s;
> }
>
> @@ -101,14 +121,14 @@ static int queue_diff(struct diff_options *o,
>
> if (S_ISDIR(mode1)) {
> /* 2 is file that is created */
> - d1 = noindex_filespec(NULL, 0);
> - d2 = noindex_filespec(name2, mode2);
> + d1 = noindex_filespec(NULL, 0, o);
> + d2 = noindex_filespec(name2, mode2, o);
> name2 = NULL;
> mode2 = 0;
> } else {
> /* 1 is file that is deleted */
> - d1 = noindex_filespec(name1, mode1);
> - d2 = noindex_filespec(NULL, 0);
> + d1 = noindex_filespec(name1, mode1, o);
> + d2 = noindex_filespec(NULL, 0, o);
> name1 = NULL;
> mode1 = 0;
> }
> @@ -189,8 +209,8 @@ static int queue_diff(struct diff_options *o,
> SWAP(name1, name2);
> }
>
> - d1 = noindex_filespec(name1, mode1);
> - d2 = noindex_filespec(name2, mode2);
> + d1 = noindex_filespec(name1, mode1, o);
> + d2 = noindex_filespec(name2, mode2, o);
> diff_queue(&diff_queued_diff, d1, d2);
> return 0;
> }
> diff --git a/diff.c b/diff.c
> index dc9965e836..740d0087b9 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -4282,18 +4282,18 @@ static void run_diff_cmd(const char *pgm,
> fprintf(o->file, "* Unmerged path %s\n", name);
> }
>
> -static void diff_fill_oid_info(struct diff_filespec *one, struct index_state *istate)
> +static void diff_fill_oid_info(struct diff_filespec *one, struct diff_options *o)
> {
> if (DIFF_FILE_VALID(one)) {
> if (!one->oid_valid) {
> struct stat st;
> - if (one->is_stdin) {
> + if (one->is_stdin || one->read_literally) {
> oidclr(&one->oid);
> return;
> }
> if (lstat(one->path, &st) < 0)
> die_errno("stat '%s'", one->path);
> - if (index_path(istate, &one->oid, one->path, &st, 0))
> + if (index_path(o->repo->index, &one->oid, one->path, &st, 0))
> die("cannot hash %s", one->path);
> }
> }
> @@ -4341,8 +4341,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
> return;
> }
>
> - diff_fill_oid_info(one, o->repo->index);
> - diff_fill_oid_info(two, o->repo->index);
> + diff_fill_oid_info(one, o);
> + diff_fill_oid_info(two, o);
>
> if (!pgm &&
> DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
> @@ -4389,8 +4389,8 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
> if (o->prefix_length)
> strip_prefix(o->prefix_length, &name, &other);
>
> - diff_fill_oid_info(p->one, o->repo->index);
> - diff_fill_oid_info(p->two, o->repo->index);
> + diff_fill_oid_info(p->one, o);
> + diff_fill_oid_info(p->two, o);
>
> builtin_diffstat(name, other, p->one, p->two,
> diffstat, o, p);
> @@ -4414,8 +4414,8 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
> if (o->prefix_length)
> strip_prefix(o->prefix_length, &name, &other);
>
> - diff_fill_oid_info(p->one, o->repo->index);
> - diff_fill_oid_info(p->two, o->repo->index);
> + diff_fill_oid_info(p->one, o);
> + diff_fill_oid_info(p->two, o);
>
> builtin_checkdiff(name, other, attr_path, p->one, p->two, o);
> }
> @@ -5159,6 +5159,8 @@ int diff_opt_parse(struct diff_options *options,
> options->flags.funccontext = 1;
> else if (!strcmp(arg, "--no-function-context"))
> options->flags.funccontext = 0;
> + else if (!strcmp(arg, "--literally"))
> + options->flags.read_literally = 1;
> else if ((argcount = parse_long_opt("output", av, &optarg))) {
> char *path = prefix_filename(prefix, optarg);
> options->file = xfopen(path, "w");
> @@ -5720,8 +5722,8 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid
> if (DIFF_PAIR_UNMERGED(p))
> continue;
>
> - diff_fill_oid_info(p->one, options->repo->index);
> - diff_fill_oid_info(p->two, options->repo->index);
> + diff_fill_oid_info(p->one, options);
> + diff_fill_oid_info(p->two, options);
>
> len1 = remove_space(p->one->path, strlen(p->one->path));
> len2 = remove_space(p->two->path, strlen(p->two->path));
> diff --git a/diff.h b/diff.h
> index ce5e8a8183..7dedd3bcd1 100644
> --- a/diff.h
> +++ b/diff.h
> @@ -97,6 +97,7 @@ struct diff_flags {
> unsigned stat_with_summary:1;
> unsigned suppress_diff_headers:1;
> unsigned dual_color_diffed_diffs:1;
> + unsigned read_literally:1;
> };
>
> static inline void diff_flags_or(struct diff_flags *a,
> diff --git a/diffcore.h b/diffcore.h
> index b651061c0e..363869447a 100644
> --- a/diffcore.h
> +++ b/diffcore.h
> @@ -48,6 +48,7 @@ struct diff_filespec {
> #define DIRTY_SUBMODULE_UNTRACKED 1
> #define DIRTY_SUBMODULE_MODIFIED 2
> unsigned is_stdin : 1;
> + unsigned read_literally : 1;
> unsigned has_more_entries : 1; /* only appear in combined diff */
> /* data should be considered "binary"; -1 means "don't know yet" */
> signed int is_binary : 2;
> diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
> index 6e0dd6f9e5..53e6bcdc19 100755
> --- a/t/t4053-diff-no-index.sh
> +++ b/t/t4053-diff-no-index.sh
> @@ -137,4 +137,32 @@ test_expect_success 'diff --no-index from repo subdir with absolute paths' '
> test_cmp expect actual
> '
>
> +test_expect_success 'diff --no-index --literally' '
> + echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
> + test_expect_code 1 \
> + git -C repo/sub \
> + diff --literally ../../non/git/a ../../non/git/b >actual &&
> + head -n 1 <actual >actual.head &&
> + test_cmp expect actual.head
> +'
> +
> +test_expect_success SYMLINKS 'diff --no-index --literally with symlinks' '
> + test_write_lines a b c >f1 &&
> + test_write_lines a d c >f2 &&
> + ln -s f1 s1 &&
> + ln -s f2 s2 &&
> + cat >expect <<-\EOF &&
> + diff --git a/s1 b/s2
> + --- a/s1
> + +++ b/s2
> + @@ -1,3 +1,3 @@
> + a
> + -b
> + +d
> + c
> + EOF
> + test_expect_code 1 git diff --no-index --literally s1 s2 >actual &&
> + test_cmp expect actual
> +'
> +
> test_done
>
^ permalink raw reply
* [PATCH 1/1] abspath_part_inside_repo: respect core.fileMode
From: Johannes Schindelin via GitGitGadget @ 2018-12-21 11:32 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Johannes Schindelin
In-Reply-To: <pull.104.git.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
If the file system is case-insensitive, we really must be careful to
ignore differences in case only.
This fixes https://github.com/git-for-windows/git/issues/735
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
setup.c | 6 +++---
t/t3700-add.sh | 7 +++++++
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/setup.c b/setup.c
index 1be5037f12..291bfb2128 100644
--- a/setup.c
+++ b/setup.c
@@ -39,7 +39,7 @@ static int abspath_part_inside_repo(char *path)
off = offset_1st_component(path);
/* check if work tree is already the prefix */
- if (wtlen <= len && !strncmp(path, work_tree, wtlen)) {
+ if (wtlen <= len && !fspathncmp(path, work_tree, wtlen)) {
if (path[wtlen] == '/') {
memmove(path, path + wtlen + 1, len - wtlen);
return 0;
@@ -59,7 +59,7 @@ static int abspath_part_inside_repo(char *path)
path++;
if (*path == '/') {
*path = '\0';
- if (strcmp(real_path(path0), work_tree) == 0) {
+ if (fspathcmp(real_path(path0), work_tree) == 0) {
memmove(path0, path + 1, len - (path - path0));
return 0;
}
@@ -68,7 +68,7 @@ static int abspath_part_inside_repo(char *path)
}
/* check whole path */
- if (strcmp(real_path(path0), work_tree) == 0) {
+ if (fspathcmp(real_path(path0), work_tree) == 0) {
*path0 = '\0';
return 0;
}
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 37729ba258..8ee4fc70ad 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -402,4 +402,11 @@ test_expect_success 'all statuses changed in folder if . is given' '
test $(git ls-files --stage | grep ^100755 | wc -l) -eq 0
'
+test_expect_success MINGW 'path is case-insensitive' '
+ path="$(pwd)/BLUB" &&
+ touch "$path" &&
+ downcased="$(echo "$path" | tr A-Z a-z)" &&
+ git add "$downcased"
+'
+
test_done
--
gitgitgadget
^ permalink raw reply related
* [PATCH 0/1] Make abspath() aware of case-insensitive filesystems
From: Johannes Schindelin via GitGitGadget @ 2018-12-21 11:32 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
It is completely legitimate these days to call git add with absolute paths.
Of course, on a case-insensitive file system, users rightfully expect the
argument to be handled case-insensitively, too. This patch makes it so.
Git for Windows carried this patch for over one and a half years already, I
think it is time to get it into git.git.
Johannes Schindelin (1):
abspath_part_inside_repo: respect core.fileMode
setup.c | 6 +++---
t/t3700-add.sh | 7 +++++++
2 files changed, 10 insertions(+), 3 deletions(-)
base-commit: b21ebb671bb7dea8d342225f0d66c41f4e54d5ca
Published-As: https://github.com/gitgitgadget/git/releases/tags/pr-104%2Fdscho%2Fcase-insensitive-abspath-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-104/dscho/case-insensitive-abspath-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/104
--
gitgitgadget
^ permalink raw reply
* Suppress reporting implicit git gc calls, when they don’t do anything
From: Дилян Палаузов @ 2018-12-21 10:27 UTC (permalink / raw)
To: git
Hello,
With git 19.2.2 after `git pull` the output was
1. Autopacking the repository in background for optimal performance.
See "git help gc" for manual housekeeping
2. error: Your local changes to the following files would be
overwritten by merge:
…
Please commit your changes or stash them before you merge.
Aborting
This implies, that `git gc` runs in the background.
Then I called `git rebase --autostash` on which the output contained
again:
“Autopacking the repository in background for optimal performance. See
"git help gc" for manual housekeeping.”
The second message means, that `git gc` is again started in the
background, before the first GC has finished. Clearly non-sense.
In practice, the second GC does not run, or exits very fast.
* Alter `git rebase --autostash` not to write, that git gc is called,
when that GC doesn’t do anything.
Regards
Дилян
^ permalink raw reply
* comment for git-config man
From: Олег Самойлов @ 2018-12-21 8:54 UTC (permalink / raw)
To: git
cite
worktree.guessRemote
With add, if no branch argument,
cite end
This was very confusing for me. Much be better if «With worktree add».
^ permalink raw reply
* Re: [PATCH] log: add %S option (like --source) to log --format
From: Issac Trotts @ 2018-12-21 5:24 UTC (permalink / raw)
To: git; +Cc: Noemi Mercado, Issac Trotts
In-Reply-To: <20181219083305.2500-1-issac.trotts@gmail.com>
Hi all, friendly ping. Is there still interest in merging this patch?
Thanks,
Issac
On Wed, Dec 19, 2018 at 12:33 AM <issac.trotts@gmail.com> wrote:
>
> From: Issac Trotts <issac.trotts@gmail.com>
>
> Make it possible to write for example
>
> git log --format="%H,%S"
>
> where the %S at the end is a new placeholder that prints out the ref
> (tag/branch) for each commit.
>
> Using %d might seem like an alternative but it only shows the ref for the last
> commit in the branch.
>
> Signed-off-by: Issac Trotts <issactrotts@google.com>
>
> ---
>
> This change is based on a question from Stack Overflow:
> https://stackoverflow.com/questions/12712775/git-get-source-information-in-format
> ---
> Documentation/pretty-formats.txt | 2 ++
> builtin/log.c | 2 +-
> log-tree.c | 1 +
> pretty.c | 15 ++++++++++
> pretty.h | 1 +
> t/t4205-log-pretty-formats.sh | 50 ++++++++++++++++++++++++++++++++
> 6 files changed, 70 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
> index 417b638cd..de6953108 100644
> --- a/Documentation/pretty-formats.txt
> +++ b/Documentation/pretty-formats.txt
> @@ -134,6 +134,8 @@ The placeholders are:
> - '%cI': committer date, strict ISO 8601 format
> - '%d': ref names, like the --decorate option of linkgit:git-log[1]
> - '%D': ref names without the " (", ")" wrapping.
> +- '%S': ref name given on the command line by which the commit was reached
> + (like `git log --source`), only works with `git log`
> - '%e': encoding
> - '%s': subject
> - '%f': sanitized subject line, suitable for a filename
> diff --git a/builtin/log.c b/builtin/log.c
> index e8e51068b..be3025657 100644
> --- a/builtin/log.c
> +++ b/builtin/log.c
> @@ -203,7 +203,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
> rev->diffopt.filter || rev->diffopt.flags.follow_renames)
> rev->always_show_header = 0;
>
> - if (source) {
> + if (source || (rev->pretty_given && (rev->commit_format == CMIT_FMT_USERFORMAT) && w.source)) {
> init_revision_sources(&revision_sources);
> rev->sources = &revision_sources;
> }
> diff --git a/log-tree.c b/log-tree.c
> index 10680c139..3cb14256e 100644
> --- a/log-tree.c
> +++ b/log-tree.c
> @@ -700,6 +700,7 @@ void show_log(struct rev_info *opt)
> ctx.color = opt->diffopt.use_color;
> ctx.expand_tabs_in_log = opt->expand_tabs_in_log;
> ctx.output_encoding = get_log_output_encoding();
> + ctx.rev = opt;
> if (opt->from_ident.mail_begin && opt->from_ident.name_begin)
> ctx.from_ident = &opt->from_ident;
> if (opt->graph)
> diff --git a/pretty.c b/pretty.c
> index b83a3ecd2..258e86e9c 100644
> --- a/pretty.c
> +++ b/pretty.c
> @@ -1084,6 +1084,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
> struct commit_list *p;
> const char *arg;
> int ch;
> + char **slot;
>
> /* these are independent of the commit */
> switch (placeholder[0]) {
> @@ -1194,6 +1195,17 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
> load_ref_decorations(NULL, DECORATE_SHORT_REFS);
> format_decorations_extended(sb, commit, c->auto_color, "", ", ", "");
> return 1;
> + case 'S': /* tag/branch like --source */
> + if (c->pretty_ctx->rev->sources == NULL) {
> + return 0;
> + }
> + slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
> + if (slot && *slot) {
> + strbuf_addstr(sb, *slot);
> + return 1;
> + } else {
> + die(_("failed to get info for %%S"));
> + }
> case 'g': /* reflog info */
> switch(placeholder[1]) {
> case 'd': /* reflog selector */
> @@ -1498,6 +1510,9 @@ static size_t userformat_want_item(struct strbuf *sb, const char *placeholder,
> case 'N':
> w->notes = 1;
> break;
> + case 'S':
> + w->source = 1;
> + break;
> }
> return 0;
> }
> diff --git a/pretty.h b/pretty.h
> index 7359d318a..87ca5dfcb 100644
> --- a/pretty.h
> +++ b/pretty.h
> @@ -60,6 +60,7 @@ static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
>
> struct userformat_want {
> unsigned notes:1;
> + unsigned source:1;
> };
>
> /* Set the flag "w->notes" if there is placeholder %N in "fmt". */
> diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
> index 978a8a66f..7df8c3d4e 100755
> --- a/t/t4205-log-pretty-formats.sh
> +++ b/t/t4205-log-pretty-formats.sh
> @@ -621,4 +621,54 @@ test_expect_success 'trailer parsing not fooled by --- line' '
> test_cmp expect actual
> '
>
> +test_expect_success 'set up %S tests' '
> + git checkout --orphan source-a &&
> + test_commit one &&
> + test_commit two &&
> + git checkout -b source-b HEAD^ &&
> + test_commit three
> +'
> +
> +test_expect_success 'log --format=%S paints branch names' '
> + cat >expect <<-\EOF &&
> + source-b
> + source-a
> + source-b
> + EOF
> + git log --format=%S source-a source-b >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'log --format=%S paints tag names' '
> + git tag -m tagged source-tag &&
> + cat >expect <<-\EOF &&
> + source-tag
> + source-a
> + source-tag
> + EOF
> + git log --format=%S source-tag source-a >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success 'log --format=%S paints symmetric ranges' '
> + cat >expect <<-\EOF &&
> + source-b
> + source-a
> + EOF
> + git log --format=%S source-a...source-b >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success '%S in git log --format works with other placeholders (part 1)' '
> + git log --format="source-b %h" source-b >expect &&
> + git log --format="%S %h" source-b >actual &&
> + test_cmp expect actual
> +'
> +
> +test_expect_success '%S in git log --format works with other placeholders (part 2)' '
> + git log --format="%h source-b" source-b >expect &&
> + git log --format="%h %S" source-b >actual &&
> + test_cmp expect actual
> +'
> +
> test_done
> --
> 2.19.1
>
^ permalink raw reply
* "git show --usage" no "usage" displayed
From: Nicholas Hsiang @ 2018-12-21 2:27 UTC (permalink / raw)
To: git
Dear git:
When I type `git remote --usage`, The command panel will prompt
'error: unknown option `usage', Then there will be `git remote`
related instructions.
But I type `git show --usage`, just display 'fatal: unrecognized
argument: --usage'.

Sorry, the previou email forgot to write the title. The previou
previou email did not remove the HTML format.
Yours sincerely,
Xiang HongAi.
--
Live Long and Prosper.
^ permalink raw reply
* (no subject)
From: Nicholas Hsiang @ 2018-12-21 2:22 UTC (permalink / raw)
To: git
Dear git:
When I type `git remote --usage`, The command panel will prompt
'error: unknown option `usage', Then there will be `git remote`
related instructions.
But I type `git show --usage`, just display 'fatal: unrecognized
argument: --usage'.

Yours sincerely,
Xiang HongAi.
--
Live Long and Prosper.
^ permalink raw reply
* Re: [PATCH] diff: add support for reading files literally with --no-index
From: brian m. carlson @ 2018-12-21 0:25 UTC (permalink / raw)
To: Jeff King; +Cc: git, Duy Nguyen, Dennis Kaarsemaker
In-Reply-To: <20181220154841.GE27361@sigill.intra.peff.net>
[-- Attachment #1: Type: text/plain, Size: 1939 bytes --]
On Thu, Dec 20, 2018 at 10:48:41AM -0500, Jeff King wrote:
> The distinction is a bit subtle, but I think treating only the actual
> top-level arguments as symlinks would solve your problem, but still
> allow a more detailed diff for the recursive cases.
Yeah, I think that would be better. I'll add a test.
> Looks like spaces for indent, whereas the context uses tabs.
Will fix.
> I think "literal" is a good way to describe this concept. If we do grow
> a config option to make this the default, then countermanding it would
> be "--no-literally", which parses a bit funny as English.
>
> If you agree with my "only the top-level" line of reasoning above, maybe
> "--literal-arguments" and "--no-literal-arguments" might make sense.
>
> We could also in theory offer several levels: no literals, top-level
> literals, everything literal, at which point it becomes a tri-state.
Yeah, this is what the POSIX symlink options (-H, -L, -P) do. I
originally came up with "--dereference" as the name, but I decided to
change it, because it doesn't affect just symlinks. I think
--literal-arguments is better.
Theoretically, we could adopt the POSIX options for symlink/pipe
handling if we want to in the future, but I think that's a decision we
should make later.
> > diff --git a/diff.c b/diff.c
> > index dc9965e836..740d0087b9 100644
> > --- a/diff.c
> > +++ b/diff.c
> > @@ -4282,18 +4282,18 @@ static void run_diff_cmd(const char *pgm,
> > fprintf(o->file, "* Unmerged path %s\n", name);
> > }
> >
> > -static void diff_fill_oid_info(struct diff_filespec *one, struct index_state *istate)
> > +static void diff_fill_oid_info(struct diff_filespec *one, struct diff_options *o)
>
> It might be worth breaking these "pass the options around" hunks into a
> separate preparatory patch.
I can do that.
--
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]
^ permalink raw reply
* Re: rebase: Ask before doing anything not undoable
From: Ricardo Biehl Pasquali @ 2018-12-21 0:23 UTC (permalink / raw)
To: Thomas Braun; +Cc: Kevin Daudt, git
In-Reply-To: <53e97c08-1eaf-5f83-a699-5666376bb4c4@virtuell-zuhause.de>
On Thu, Dec 20, 2018 at 10:37:00PM +0100, Thomas Braun wrote:
> The git rebase documentation has
>
> ORIG_HEAD is set to point at the tip of the branch before the reset.
>
> so doing
>
> git reset ORIG_HEAD
>
> does reset to the state before the rebase.
That's pretty easy :-)
> For avoiding the original problem of --co completing to
> --committer-date-is-author-date I'm using the alias rc for git rebase
> --continue.
It's definetly an alternative. Anyway, ORIG_HEAD reset is
sufficient for the cases when enter is hit before noticing
the completion string.
Thank you!
pasquali
^ permalink raw reply
* RE: error: Use of uninitialized value $hash in chomp
From: Andrew Shearer @ 2018-12-21 0:15 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason; +Cc: git@vger.kernel.org, Eric Wong
In-Reply-To: <874lb9fika.fsf@evledraar.gmail.com>
Hi
Thanks for reply, but sorry I don't know how to do that - I don't have the git source code or know how to debug it.
Is there another way I can capture logging/debugging information while running "git svn clone" and send it to you?
Thanks
Andrew Shearer / Web Developer
DDI 021 469 888 / andrew@terabyte.co.nz
/TERABYTE
-----Original Message-----
From: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Sent: Thursday, 20 December 2018 8:00 AM
To: Andrew Shearer <andrew@terabyte.co.nz>
Cc: git@vger.kernel.org; Eric Wong <e@80x24.org>
Subject: Re: error: Use of uninitialized value $hash in chomp
On Wed, Dec 19 2018, Andrew Shearer wrote:
> Hello
>
> I am using a "git svn clone" command to extract our project history from svn into git.
> About 30m into the process it fails with:
>
> r50739 = 2a1491de1353b1e3cce50d8f9d383407218a44f1
> (refs/remotes/git-svn)
> fatal: Cannot open '.git/Git_svn_delta_33316_0_UkxiJV': Permission
> denied Use of uninitialized value $hash in chomp at C:/Program Files/Git/mingw64/share/perl5/Git.pm line 929, <GEN11> line 36311.
> hash-object -w --stdin-paths --no-filters: command returned error: 128
>
> error closing pipe: Bad file descriptor at C:/Program Files/Git/mingw64/libexec/git-core\git-svn line 0.
> error closing pipe: Bad file descriptor at C:/Program Files/Git/mingw64/libexec/git-core\git-svn line 0.
> (in cleanup) at /usr/share/perl5/vendor_perl/Error.pm line 198 during global destruction.
>
> I tried updating to the latest build, 2.20.1.windows, but it still fails.
>
> There is nothing particularly special about svn changeset 50739 that I can see compared to any other.
> Anyone know why this might be failing or how I could resolve it?
That "Permission denied" looks scary. Don't know how git-svn gets into this, but try with this patch on top:
diff --git a/perl/Git.pm b/perl/Git.pm
index d856930b2e..f5d15895d3 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -926,7 +926,13 @@ sub hash_and_insert_object {
throw Error::Simple("out pipe went bad");
}
- chomp(my $hash = <$in>);
+ my $hash = <$in>;
+ unless (defined $hash) {
+ sub noes { die "blah" }
+ noes();
+ } else {
+ chomp($hash);
+ }
unless (defined($hash)) {
$self->_close_hash_and_insert_object();
throw Error::Simple("in pipe went bad");
Then run:
perl -d $(git --exec-path)/git-svn
Set a breakpoint at that "noes" with:
DB<1> b Git::noes
Continue:
DB<2> c
Then when it stops there get a backtrace with "T":
DB<2> T
@ = DB::DB called from file 'perl/Git.pm' line 931
. = Git::noes() called from file 'perl/Git.pm' line 932
. = Git::hash_and_insert_object(ref(Git), 'Makefile') called from -e line 1
And see if you can get any other relevant info out of the debugger. See "perldoc perldebug".
^ permalink raw reply
* Re: [PATCH] diff: add support for reading files literally with --no-index
From: brian m. carlson @ 2018-12-20 23:54 UTC (permalink / raw)
To: Ævar Arnfjörð Bjarmason
Cc: git, Jeff King, Duy Nguyen, Dennis Kaarsemaker
In-Reply-To: <871s6bg9hx.fsf@evledraar.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 761 bytes --]
On Thu, Dec 20, 2018 at 10:43:06PM +0100, Ævar Arnfjörð Bjarmason wrote:
>
> On Thu, Dec 20 2018, brian m. carlson wrote:
>
> > We don't include a test for the pipe scenario because I couldn't get
> > that case to work in portable shell (although of course it works in
> > bash). I have, however, tested it on both macOS and Linux. No clue how
> > this works on Windows.
>
> You can (and should) add tests using the PROCESS_SUBSTITUTION prereq
> Dennis used in an earlier version of this:
> https://public-inbox.org/git/20170113102021.6054-3-dennis@kaarsemaker.net/
I'm happy to steal that code. I didn't know this had come up before, so
I didn't think of it.
--
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]
^ permalink raw reply
* Re: [PATCH 1/5] compat/obstack: fix -Wcast-function-type warnings
From: Ævar Arnfjörð Bjarmason @ 2018-12-20 23:12 UTC (permalink / raw)
To: SZEDER Gábor
Cc: Junio C Hamano, Jonathan Nieder, Johannes Schindelin, git
In-Reply-To: <20181220162452.17732-2-szeder.dev@gmail.com>
On Thu, Dec 20 2018, SZEDER Gábor wrote:
> When building Git with GCC 8.2.0 (at least from Homebrew on macOS,
> DEVELOPER flags enabled) one is greeted with a screenful of compiler
> errors:
>
> compat/obstack.c: In function '_obstack_begin':
> compat/obstack.c:162:17: error: cast between incompatible function types from 'void * (*)(long int)' to 'struct _obstack_chunk * (*)(void *, long int)' [-Werror=cast-function-type]
> h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
> ^
> compat/obstack.c:163:16: error: cast between incompatible function types from 'void (*)(void *)' to 'void (*)(void *, struct _obstack_chunk *)' [-Werror=cast-function-type]
> h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
> ^
> compat/obstack.c:116:8: error: cast between incompatible function types from 'struct _obstack_chunk * (*)(void *, long int)' to 'struct _obstack_chunk * (*)(long int)' [-Werror=cast-function-type]
> : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
> ^
> compat/obstack.c:168:22: note: in expansion of macro 'CALL_CHUNKFUN'
> chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
> ^~~~~~~~~~~~~
> <snip>
We originally got this from now-discontinued eglibc, but I notice that
glibc.git's malloc/obstack.[ch]'s diff also changes these lines. If you
backport those do does that fix this warning?
I.e. is this another case where we're blindly fixing bugs but should
just re-import upstream's code instead?
^ permalink raw reply
* [PATCH v6 1/1] protocol: advertise multiple supported versions
From: Josh Steadmon @ 2018-12-20 21:58 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1545342797.git.steadmon@google.com>
Currently the client advertises that it supports the wire protocol
version set in the protocol.version config. However, not all services
support the same set of protocol versions. For example, git-receive-pack
supports v1 and v0, but not v2. If a client connects to git-receive-pack
and requests v2, it will instead be downgraded to v0. Other services,
such as git-upload-archive, do not do any version negotiation checks.
This patch creates a protocol version registry. Individual client and
server programs register all the protocol versions they support prior to
communicating with a remote instance. Versions should be listed in
preference order; the version specified in protocol.version will
automatically be moved to the front of the registry.
The protocol version registry is passed to remote helpers via the
GIT_PROTOCOL environment variable.
Clients now advertise the full list of registered versions. Servers
select the first allowed version from this advertisement.
Additionally, remove special cases around advertising version=0.
Previously we avoided adding version advertisements to the client's
initial connection request if the client wanted version=0. However,
including these advertisements does not change the version negotiation
behavior, so it's better to have simpler code. As a side effect, this
means that client operations over SSH will always include a
"SendEnv=GIT_PROTOCOL" option on the SSH command line.
While we're at it, remove unnecessary externs from function declarations
in protocol.h.
Signed-off-by: Josh Steadmon <steadmon@google.com>
---
builtin/archive.c | 3 +
builtin/clone.c | 4 ++
builtin/fetch-pack.c | 4 ++
builtin/fetch.c | 5 ++
builtin/ls-remote.c | 5 ++
builtin/pull.c | 5 ++
builtin/push.c | 4 ++
builtin/receive-pack.c | 3 +
builtin/send-pack.c | 3 +
builtin/upload-archive.c | 3 +
builtin/upload-pack.c | 4 ++
connect.c | 52 +++++++--------
protocol.c | 122 +++++++++++++++++++++++++++++++++---
protocol.h | 23 ++++++-
remote-curl.c | 27 +++++---
t/t5551-http-fetch-smart.sh | 1 +
t/t5570-git-daemon.sh | 2 +-
t/t5601-clone.sh | 38 +++++------
t/t5700-protocol-v1.sh | 8 +--
t/t5702-protocol-v2.sh | 16 +++--
transport-helper.c | 6 ++
21 files changed, 256 insertions(+), 82 deletions(-)
diff --git a/builtin/archive.c b/builtin/archive.c
index e74f675390..8adb9f381b 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -8,6 +8,7 @@
#include "transport.h"
#include "parse-options.h"
#include "pkt-line.h"
+#include "protocol.h"
#include "sideband.h"
static void create_output_file(const char *output_file)
@@ -94,6 +95,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
OPT_END()
};
+ register_allowed_protocol_version(protocol_v0);
+
argc = parse_options(argc, argv, prefix, local_opts, NULL,
PARSE_OPT_KEEP_ALL);
diff --git a/builtin/clone.c b/builtin/clone.c
index fd2c3ef090..1651a950b6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -900,6 +900,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
struct refspec rs = REFSPEC_INIT_FETCH;
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
fetch_if_missing = 0;
packet_trace_identity("clone");
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 1a1bc63566..cba935e4d3 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -57,6 +57,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
fetch_if_missing = 0;
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
packet_trace_identity("fetch-pack");
memset(&args, 0, sizeof(args));
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 61bec5d213..2a20cf8bfd 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -21,6 +21,7 @@
#include "argv-array.h"
#include "utf8.h"
#include "packfile.h"
+#include "protocol.h"
#include "list-objects-filter-options.h"
static const char * const builtin_fetch_usage[] = {
@@ -1476,6 +1477,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
int prune_tags_ok = 1;
struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
packet_trace_identity("fetch");
fetch_if_missing = 0;
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 1a25df7ee1..ea685e8bb9 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -1,5 +1,6 @@
#include "builtin.h"
#include "cache.h"
+#include "protocol.h"
#include "transport.h"
#include "ref-filter.h"
#include "remote.h"
@@ -80,6 +81,10 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
memset(&ref_array, 0, sizeof(ref_array));
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
argc = parse_options(argc, argv, prefix, options, ls_remote_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
dest = argv[0];
diff --git a/builtin/pull.c b/builtin/pull.c
index 681c127a07..cb64146834 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -9,6 +9,7 @@
#include "config.h"
#include "builtin.h"
#include "parse-options.h"
+#include "protocol.h"
#include "exec-cmd.h"
#include "run-command.h"
#include "sha1-array.h"
@@ -849,6 +850,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
struct object_id rebase_fork_point;
int autostash;
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
diff --git a/builtin/push.c b/builtin/push.c
index d09a42062c..10d8abe829 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -10,6 +10,7 @@
#include "remote.h"
#include "transport.h"
#include "parse-options.h"
+#include "protocol.h"
#include "submodule.h"
#include "submodule-config.h"
#include "send-pack.h"
@@ -587,6 +588,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_END()
};
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
packet_trace_identity("push");
git_config(git_push_config, &flags);
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c17ce94e12..030cb7b7ec 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1929,6 +1929,9 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
packet_trace_identity("receive-pack");
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0);
if (argc > 1)
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 8e3c7490f7..f48bd1306b 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -184,6 +184,9 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
OPT_END()
};
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
git_config(send_pack_config, NULL);
argc = parse_options(argc, argv, prefix, options, send_pack_usage, 0);
if (argc > 0) {
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index 25d9116356..791cbe80a6 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -5,6 +5,7 @@
#include "builtin.h"
#include "archive.h"
#include "pkt-line.h"
+#include "protocol.h"
#include "sideband.h"
#include "run-command.h"
#include "argv-array.h"
@@ -80,6 +81,8 @@ int cmd_upload_archive(int argc, const char **argv, const char *prefix)
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(upload_archive_usage);
+ register_allowed_protocol_version(protocol_v0);
+
/*
* Set up sideband subprocess.
*
diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
index 42dc4da5a1..293dd45b9e 100644
--- a/builtin/upload-pack.c
+++ b/builtin/upload-pack.c
@@ -33,6 +33,10 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
packet_trace_identity("upload-pack");
read_replace_refs = 0;
+ register_allowed_protocol_version(protocol_v2);
+ register_allowed_protocol_version(protocol_v1);
+ register_allowed_protocol_version(protocol_v0);
+
argc = parse_options(argc, argv, NULL, options, upload_pack_usage, 0);
if (argc != 1)
diff --git a/connect.c b/connect.c
index 94547e5056..57266b6cec 100644
--- a/connect.c
+++ b/connect.c
@@ -1046,7 +1046,7 @@ static enum ssh_variant determine_ssh_variant(const char *ssh_command,
*/
static struct child_process *git_connect_git(int fd[2], char *hostandport,
const char *path, const char *prog,
- enum protocol_version version,
+ const struct strbuf *version_advert,
int flags)
{
struct child_process *conn;
@@ -1084,12 +1084,9 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,
prog, path, 0,
target_host, 0);
- /* If using a new version put that stuff here after a second null byte */
- if (version > 0) {
- strbuf_addch(&request, '\0');
- strbuf_addf(&request, "version=%d%c",
- version, '\0');
- }
+ /* Add version fields after a second null byte */
+ strbuf_addch(&request, '\0');
+ strbuf_addf(&request, "%s%c", version_advert->buf, '\0');
packet_write(fd[1], request.buf, request.len);
@@ -1104,14 +1101,13 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,
*/
static void push_ssh_options(struct argv_array *args, struct argv_array *env,
enum ssh_variant variant, const char *port,
- enum protocol_version version, int flags)
+ const struct strbuf *version_advert, int flags)
{
- if (variant == VARIANT_SSH &&
- version > 0) {
+ if (variant == VARIANT_SSH) {
argv_array_push(args, "-o");
argv_array_push(args, "SendEnv=" GIT_PROTOCOL_ENVIRONMENT);
- argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
- version);
+ argv_array_pushf(env, GIT_PROTOCOL_ENVIRONMENT "=%s",
+ version_advert->buf);
}
if (flags & CONNECT_IPV4) {
@@ -1164,7 +1160,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,
/* Prepare a child_process for use by Git's SSH-tunneled transport. */
static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
- const char *port, enum protocol_version version,
+ const char *port, const struct strbuf *version_advert,
int flags)
{
const char *ssh;
@@ -1198,15 +1194,16 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,
argv_array_push(&detect.args, ssh);
argv_array_push(&detect.args, "-G");
- push_ssh_options(&detect.args, &detect.env_array,
- VARIANT_SSH, port, version, flags);
+ push_ssh_options(&detect.args, &detect.env_array, VARIANT_SSH,
+ port, version_advert, flags);
argv_array_push(&detect.args, ssh_host);
variant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;
}
argv_array_push(&conn->args, ssh);
- push_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);
+ push_ssh_options(&conn->args, &conn->env_array, variant, port,
+ version_advert, flags);
argv_array_push(&conn->args, ssh_host);
}
@@ -1226,16 +1223,10 @@ struct child_process *git_connect(int fd[2], const char *url,
{
char *hostandport, *path;
struct child_process *conn;
+ struct strbuf version_advert = STRBUF_INIT;
enum protocol protocol;
- enum protocol_version version = get_protocol_version_config();
- /*
- * NEEDSWORK: If we are trying to use protocol v2 and we are planning
- * to perform a push, then fallback to v0 since the client doesn't know
- * how to push yet using v2.
- */
- if (version == protocol_v2 && !strcmp("git-receive-pack", prog))
- version = protocol_v0;
+ get_client_protocol_version_advertisement(&version_advert);
/* Without this we cannot rely on waitpid() to tell
* what happened to our children.
@@ -1250,7 +1241,8 @@ struct child_process *git_connect(int fd[2], const char *url,
printf("Diag: path=%s\n", path ? path : "NULL");
conn = NULL;
} else if (protocol == PROTO_GIT) {
- conn = git_connect_git(fd, hostandport, path, prog, version, flags);
+ conn = git_connect_git(fd, hostandport, path, prog,
+ &version_advert, flags);
} else {
struct strbuf cmd = STRBUF_INIT;
const char *const *var;
@@ -1293,13 +1285,13 @@ struct child_process *git_connect(int fd[2], const char *url,
strbuf_release(&cmd);
return NULL;
}
- fill_ssh_args(conn, ssh_host, port, version, flags);
+ fill_ssh_args(conn, ssh_host, port, &version_advert,
+ flags);
} else {
transport_check_allowed("file");
- if (version > 0) {
- argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d",
- version);
- }
+ argv_array_pushf(&conn->env_array,
+ GIT_PROTOCOL_ENVIRONMENT "=%s",
+ version_advert.buf);
}
argv_array_push(&conn->args, cmd.buf);
diff --git a/protocol.c b/protocol.c
index 5e636785d1..5664bd7a05 100644
--- a/protocol.c
+++ b/protocol.c
@@ -2,18 +2,43 @@
#include "config.h"
#include "protocol.h"
+static enum protocol_version *allowed_versions;
+static int nr_allowed_versions;
+static int alloc_allowed_versions;
+static int version_registration_locked = 0;
+
+static const char protocol_v0_string[] = "0";
+static const char protocol_v1_string[] = "1";
+static const char protocol_v2_string[] = "2";
+
static enum protocol_version parse_protocol_version(const char *value)
{
- if (!strcmp(value, "0"))
+ if (!strcmp(value, protocol_v0_string))
return protocol_v0;
- else if (!strcmp(value, "1"))
+ else if (!strcmp(value, protocol_v1_string))
return protocol_v1;
- else if (!strcmp(value, "2"))
+ else if (!strcmp(value, protocol_v2_string))
return protocol_v2;
else
return protocol_unknown_version;
}
+/* Return the text representation of a wire protocol version. */
+static const char *format_protocol_version(enum protocol_version version)
+{
+ switch (version) {
+ case protocol_v0:
+ return protocol_v0_string;
+ case protocol_v1:
+ return protocol_v1_string;
+ case protocol_v2:
+ return protocol_v2_string;
+ case protocol_unknown_version:
+ die(_("Unrecognized protocol version"));
+ }
+ die(_("Unrecognized protocol_version"));
+}
+
enum protocol_version get_protocol_version_config(void)
{
const char *value;
@@ -30,6 +55,85 @@ enum protocol_version get_protocol_version_config(void)
return protocol_v0;
}
+void register_allowed_protocol_version(enum protocol_version version)
+{
+ if (version_registration_locked)
+ BUG("late attempt to register an allowed protocol version");
+
+ ALLOC_GROW(allowed_versions, nr_allowed_versions + 1,
+ alloc_allowed_versions);
+ allowed_versions[nr_allowed_versions++] = version;
+}
+
+void register_allowed_protocol_versions_from_env(void)
+{
+ const char *git_protocol = getenv(GIT_PROTOCOL_ENVIRONMENT);
+ const char *version_str;
+ struct string_list version_list = STRING_LIST_INIT_DUP;
+ struct string_list_item *version;
+
+ if (!git_protocol)
+ return;
+
+ string_list_split(&version_list, git_protocol, ':', -1);
+ for_each_string_list_item(version, &version_list) {
+ if (skip_prefix(version->string, "version=", &version_str))
+ register_allowed_protocol_version(
+ parse_protocol_version(version_str));
+ }
+ string_list_clear(&version_list, 0);
+}
+
+static int is_allowed_protocol_version(enum protocol_version version)
+{
+ int i;
+ version_registration_locked = 1;
+ for (i = 0; i < nr_allowed_versions; i++)
+ if (version == allowed_versions[i])
+ return 1;
+ return 0;
+}
+
+void get_client_protocol_version_advertisement(struct strbuf *advert)
+{
+ int i, tmp_nr = nr_allowed_versions;
+ enum protocol_version *tmp_allowed_versions, config_version;
+ strbuf_reset(advert);
+
+ version_registration_locked = 1;
+
+ config_version = get_protocol_version_config();
+ if (config_version == protocol_v0) {
+ strbuf_addstr(advert, "version=0");
+ return;
+ }
+
+ if (tmp_nr > 0) {
+ ALLOC_ARRAY(tmp_allowed_versions, tmp_nr);
+ copy_array(tmp_allowed_versions, allowed_versions, tmp_nr,
+ sizeof(enum protocol_version));
+ } else {
+ ALLOC_ARRAY(tmp_allowed_versions, 1);
+ tmp_nr = 1;
+ tmp_allowed_versions[0] = config_version;
+ }
+
+ if (tmp_allowed_versions[0] != config_version)
+ for (i = 1; i < nr_allowed_versions; i++)
+ if (tmp_allowed_versions[i] == config_version) {
+ SWAP(tmp_allowed_versions[0],
+ tmp_allowed_versions[i]);
+ }
+
+ strbuf_addf(advert, "version=%s",
+ format_protocol_version(tmp_allowed_versions[0]));
+ for (i = 1; i < tmp_nr; i++)
+ strbuf_addf(advert, ":version=%s",
+ format_protocol_version(tmp_allowed_versions[i]));
+
+ free(tmp_allowed_versions);
+}
+
enum protocol_version determine_protocol_version_server(void)
{
const char *git_protocol = getenv(GIT_PROTOCOL_ENVIRONMENT);
@@ -38,9 +142,10 @@ enum protocol_version determine_protocol_version_server(void)
/*
* Determine which protocol version the client has requested. Since
* multiple 'version' keys can be sent by the client, indicating that
- * the client is okay to speak any of them, select the greatest version
- * that the client has requested. This is due to the assumption that
- * the most recent protocol version will be the most state-of-the-art.
+ * the client is okay to speak any of them, select the first
+ * recognizable version that the client has requested. This is due to
+ * the assumption that the protocol versions will be listed in
+ * preference order.
*/
if (git_protocol) {
struct string_list list = STRING_LIST_INIT_DUP;
@@ -53,8 +158,11 @@ enum protocol_version determine_protocol_version_server(void)
if (skip_prefix(item->string, "version=", &value)) {
v = parse_protocol_version(value);
- if (v > version)
+ if (v != protocol_unknown_version &&
+ is_allowed_protocol_version(v)) {
version = v;
+ break;
+ }
}
}
diff --git a/protocol.h b/protocol.h
index 2ad35e433c..88330fd0ee 100644
--- a/protocol.h
+++ b/protocol.h
@@ -14,7 +14,24 @@ enum protocol_version {
* 'protocol.version' config. If unconfigured, a value of 'protocol_v0' is
* returned.
*/
-extern enum protocol_version get_protocol_version_config(void);
+enum protocol_version get_protocol_version_config(void);
+
+/*
+ * Register an allowable protocol version for a given operation. Registration
+ * must occur before attempting to advertise a version to a server process.
+ */
+void register_allowed_protocol_version(enum protocol_version version);
+
+/*
+ * Register allowable protocol versions from the GIT_PROTOCOL environment var.
+ */
+void register_allowed_protocol_versions_from_env(void);
+
+/*
+ * Fill a strbuf with a version advertisement string suitable for use in the
+ * GIT_PROTOCOL environment variable or similar version negotiation field.
+ */
+void get_client_protocol_version_advertisement(struct strbuf *advert);
/*
* Used by a server to determine which protocol version should be used based on
@@ -23,12 +40,12 @@ extern enum protocol_version get_protocol_version_config(void);
* request a particular protocol version, a default of 'protocol_v0' will be
* used.
*/
-extern enum protocol_version determine_protocol_version_server(void);
+enum protocol_version determine_protocol_version_server(void);
/*
* Used by a client to determine which protocol version the server is speaking
* based on the server's initial response.
*/
-extern enum protocol_version determine_protocol_version_client(const char *server_response);
+enum protocol_version determine_protocol_version_client(const char *server_response);
#endif /* PROTOCOL_H */
diff --git a/remote-curl.c b/remote-curl.c
index fb28309e85..6ffefe5169 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -330,6 +330,19 @@ static int get_protocol_http_header(enum protocol_version version,
return 0;
}
+static int get_client_protocol_http_header(const struct strbuf *version_advert,
+ struct strbuf *header)
+{
+ if (version_advert->len > 0) {
+ strbuf_addf(header, GIT_PROTOCOL_HEADER ": %s",
+ version_advert->buf);
+
+ return 1;
+ }
+
+ return 0;
+}
+
static struct discovery *discover_refs(const char *service, int for_push)
{
struct strbuf exp = STRBUF_INIT;
@@ -339,11 +352,11 @@ static struct discovery *discover_refs(const char *service, int for_push)
struct strbuf refs_url = STRBUF_INIT;
struct strbuf effective_url = STRBUF_INIT;
struct strbuf protocol_header = STRBUF_INIT;
+ struct strbuf version_advert = STRBUF_INIT;
struct string_list extra_headers = STRING_LIST_INIT_DUP;
struct discovery *last = last_discovery;
int http_ret, maybe_smart = 0;
struct http_get_options http_options;
- enum protocol_version version = get_protocol_version_config();
if (last && !strcmp(service, last->service))
return last;
@@ -360,16 +373,10 @@ static struct discovery *discover_refs(const char *service, int for_push)
strbuf_addf(&refs_url, "service=%s", service);
}
- /*
- * NEEDSWORK: If we are trying to use protocol v2 and we are planning
- * to perform a push, then fallback to v0 since the client doesn't know
- * how to push yet using v2.
- */
- if (version == protocol_v2 && !strcmp("git-receive-pack", service))
- version = protocol_v0;
+ get_client_protocol_version_advertisement(&version_advert);
/* Add the extra Git-Protocol header */
- if (get_protocol_http_header(version, &protocol_header))
+ if (get_client_protocol_http_header(&version_advert, &protocol_header))
string_list_append(&extra_headers, protocol_header.buf);
memset(&http_options, 0, sizeof(http_options));
@@ -1327,6 +1334,8 @@ int cmd_main(int argc, const char **argv)
struct strbuf buf = STRBUF_INIT;
int nongit;
+ register_allowed_protocol_versions_from_env();
+
setup_git_directory_gently(&nongit);
if (argc < 2) {
error("remote-curl: usage: git remote-curl <remote> [<url>]");
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 771f36f9ff..343bf3aafa 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -28,6 +28,7 @@ cat >exp <<EOF
> Accept: */*
> Accept-Encoding: ENCODINGS
> Pragma: no-cache
+> Git-Protocol: version=0
< HTTP/1.1 200 OK
< Pragma: no-cache
< Cache-Control: no-cache, max-age=0, must-revalidate
diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh
index 7466aad111..d528e91630 100755
--- a/t/t5570-git-daemon.sh
+++ b/t/t5570-git-daemon.sh
@@ -186,7 +186,7 @@ test_expect_success 'hostname cannot break out of directory' '
test_expect_success 'daemon log records all attributes' '
cat >expect <<-\EOF &&
Extended attribute "host": localhost
- Extended attribute "protocol": version=1
+ Extended attribute "protocol": version=1:version=2:version=0
EOF
>daemon.log &&
GIT_OVERRIDE_VIRTUAL_HOST=localhost \
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index ddaa96ac4f..c4dbf1f779 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -346,7 +346,7 @@ expect_ssh () {
test_expect_success 'clone myhost:src uses ssh' '
git clone myhost:src ssh-clone &&
- expect_ssh myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL" myhost src
'
test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
@@ -357,12 +357,12 @@ test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
test_expect_success 'bracketed hostnames are still ssh' '
git clone "[myhost:123]:src" ssh-bracket-clone &&
- expect_ssh "-p 123" myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL -p 123" myhost src
'
test_expect_success 'OpenSSH variant passes -4' '
git clone -4 "[myhost:123]:src" ssh-ipv4-clone &&
- expect_ssh "-4 -p 123" myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL -4 -p 123" myhost src
'
test_expect_success 'variant can be overridden' '
@@ -406,7 +406,7 @@ test_expect_success 'OpenSSH-like uplink is treated as ssh' '
GIT_SSH="$TRASH_DIRECTORY/uplink" &&
test_when_finished "GIT_SSH=\"\$TRASH_DIRECTORY/ssh\$X\"" &&
git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink &&
- expect_ssh "-p 123" myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL -p 123" myhost src
'
test_expect_success 'plink is treated specially (as putty)' '
@@ -446,14 +446,14 @@ test_expect_success 'GIT_SSH_VARIANT overrides plink detection' '
copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
GIT_SSH_VARIANT=ssh \
git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
- expect_ssh "-p 123" myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL -p 123" myhost src
'
test_expect_success 'ssh.variant overrides plink detection' '
copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
git -c ssh.variant=ssh \
clone "[myhost:123]:src" ssh-bracket-clone-variant-2 &&
- expect_ssh "-p 123" myhost src
+ expect_ssh "-o SendEnv=GIT_PROTOCOL -p 123" myhost src
'
test_expect_success 'GIT_SSH_VARIANT overrides plink detection to plink' '
@@ -488,7 +488,7 @@ test_clone_url () {
}
test_expect_success !MINGW 'clone c:temp is ssl' '
- test_clone_url c:temp c temp
+ test_clone_url c:temp "-o SendEnv=GIT_PROTOCOL" c temp
'
test_expect_success MINGW 'clone c:temp is dos drive' '
@@ -499,7 +499,7 @@ test_expect_success MINGW 'clone c:temp is dos drive' '
for repo in rep rep/home/project 123
do
test_expect_success "clone host:$repo" '
- test_clone_url host:$repo host $repo
+ test_clone_url host:$repo "-o SendEnv=GIT_PROTOCOL" host $repo
'
done
@@ -507,16 +507,16 @@ done
for repo in rep rep/home/project 123
do
test_expect_success "clone [::1]:$repo" '
- test_clone_url [::1]:$repo ::1 "$repo"
+ test_clone_url [::1]:$repo "-o SendEnv=GIT_PROTOCOL" ::1 "$repo"
'
done
#home directory
test_expect_success "clone host:/~repo" '
- test_clone_url host:/~repo host "~repo"
+ test_clone_url host:/~repo "-o SendEnv=GIT_PROTOCOL" host "~repo"
'
test_expect_success "clone [::1]:/~repo" '
- test_clone_url [::1]:/~repo ::1 "~repo"
+ test_clone_url [::1]:/~repo "-o SendEnv=GIT_PROTOCOL" ::1 "~repo"
'
# Corner cases
@@ -532,22 +532,22 @@ done
for tcol in "" :
do
test_expect_success "clone ssh://host.xz$tcol/home/user/repo" '
- test_clone_url "ssh://host.xz$tcol/home/user/repo" host.xz /home/user/repo
+ test_clone_url "ssh://host.xz$tcol/home/user/repo" "-o SendEnv=GIT_PROTOCOL" host.xz /home/user/repo
'
# from home directory
test_expect_success "clone ssh://host.xz$tcol/~repo" '
- test_clone_url "ssh://host.xz$tcol/~repo" host.xz "~repo"
+ test_clone_url "ssh://host.xz$tcol/~repo" "-o SendEnv=GIT_PROTOCOL" host.xz "~repo"
'
done
# with port number
test_expect_success 'clone ssh://host.xz:22/home/user/repo' '
- test_clone_url "ssh://host.xz:22/home/user/repo" "-p 22 host.xz" "/home/user/repo"
+ test_clone_url "ssh://host.xz:22/home/user/repo" "-o SendEnv=GIT_PROTOCOL -p 22 host.xz" "/home/user/repo"
'
# from home directory with port number
test_expect_success 'clone ssh://host.xz:22/~repo' '
- test_clone_url "ssh://host.xz:22/~repo" "-p 22 host.xz" "~repo"
+ test_clone_url "ssh://host.xz:22/~repo" "-o SendEnv=GIT_PROTOCOL -p 22 host.xz" "~repo"
'
#IPv6
@@ -555,7 +555,7 @@ for tuah in ::1 [::1] [::1]: user@::1 user@[::1] user@[::1]: [user@::1] [user@::
do
ehost=$(echo $tuah | sed -e "s/1]:/1]/" | tr -d "[]")
test_expect_success "clone ssh://$tuah/home/user/repo" "
- test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo
+ test_clone_url ssh://$tuah/home/user/repo '-o SendEnv=GIT_PROTOCOL' $ehost /home/user/repo
"
done
@@ -564,7 +564,7 @@ for tuah in ::1 [::1] user@::1 user@[::1] [user@::1]
do
euah=$(echo $tuah | tr -d "[]")
test_expect_success "clone ssh://$tuah/~repo" "
- test_clone_url ssh://$tuah/~repo $euah '~repo'
+ test_clone_url ssh://$tuah/~repo '-o SendEnv=GIT_PROTOCOL' $euah '~repo'
"
done
@@ -573,7 +573,7 @@ for tuah in [::1] user@[::1] [user@::1]
do
euah=$(echo $tuah | tr -d "[]")
test_expect_success "clone ssh://$tuah:22/home/user/repo" "
- test_clone_url ssh://$tuah:22/home/user/repo '-p 22' $euah /home/user/repo
+ test_clone_url ssh://$tuah:22/home/user/repo '-o SendEnv=GIT_PROTOCOL -p 22' $euah /home/user/repo
"
done
@@ -582,7 +582,7 @@ for tuah in [::1] user@[::1] [user@::1]
do
euah=$(echo $tuah | tr -d "[]")
test_expect_success "clone ssh://$tuah:22/~repo" "
- test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo'
+ test_clone_url ssh://$tuah:22/~repo '-o SendEnv=GIT_PROTOCOL -p 22' $euah '~repo'
"
done
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index ba86a44eb1..2e56c79233 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -26,7 +26,7 @@ test_expect_success 'clone with git:// using protocol v1' '
test_cmp expect actual &&
# Client requested to use protocol v1
- grep "clone> .*\\\0\\\0version=1\\\0$" log &&
+ grep "clone> .*\\\0\\\0version=1.*\\\0$" log &&
# Server responded using protocol v1
grep "clone< version 1" log
'
@@ -42,7 +42,7 @@ test_expect_success 'fetch with git:// using protocol v1' '
test_cmp expect actual &&
# Client requested to use protocol v1
- grep "fetch> .*\\\0\\\0version=1\\\0$" log &&
+ grep "fetch> .*\\\0\\\0version=1.*\\\0$" log &&
# Server responded using protocol v1
grep "fetch< version 1" log
'
@@ -56,7 +56,7 @@ test_expect_success 'pull with git:// using protocol v1' '
test_cmp expect actual &&
# Client requested to use protocol v1
- grep "fetch> .*\\\0\\\0version=1\\\0$" log &&
+ grep "fetch> .*\\\0\\\0version=1.*\\\0$" log &&
# Server responded using protocol v1
grep "fetch< version 1" log
'
@@ -74,7 +74,7 @@ test_expect_success 'push with git:// using protocol v1' '
test_cmp expect actual &&
# Client requested to use protocol v1
- grep "push> .*\\\0\\\0version=1\\\0$" log &&
+ grep "push> .*\\\0\\\0version=1.*\\\0$" log &&
# Server responded using protocol v1
grep "push< version 1" log
'
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 3beeed4546..78c17c25e4 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -24,7 +24,7 @@ test_expect_success 'list refs with git:// using protocol v2' '
ls-remote --symref "$GIT_DAEMON_URL/parent" >actual &&
# Client requested to use protocol v2
- grep "git> .*\\\0\\\0version=2\\\0$" log &&
+ grep "git> .*\\\0\\\0version=2.*\\\0$" log &&
# Server responded using protocol v2
grep "git< version 2" log &&
@@ -56,7 +56,7 @@ test_expect_success 'clone with git:// using protocol v2' '
test_cmp expect actual &&
# Client requested to use protocol v2
- grep "clone> .*\\\0\\\0version=2\\\0$" log &&
+ grep "clone> .*\\\0\\\0version=2.*\\\0$" log &&
# Server responded using protocol v2
grep "clone< version 2" log
'
@@ -74,7 +74,7 @@ test_expect_success 'fetch with git:// using protocol v2' '
test_cmp expect actual &&
# Client requested to use protocol v2
- grep "fetch> .*\\\0\\\0version=2\\\0$" log &&
+ grep "fetch> .*\\\0\\\0version=2.*\\\0$" log &&
# Server responded using protocol v2
grep "fetch< version 2" log
'
@@ -90,7 +90,7 @@ test_expect_success 'pull with git:// using protocol v2' '
test_cmp expect actual &&
# Client requested to use protocol v2
- grep "fetch> .*\\\0\\\0version=2\\\0$" log &&
+ grep "fetch> .*\\\0\\\0version=2.*\\\0$" log &&
# Server responded using protocol v2
grep "fetch< version 2" log
'
@@ -476,7 +476,7 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' '
test_when_finished "rm -f log" &&
# Till v2 for push is designed, make sure that if a client has
# protocol.version configured to use v2, that the client instead falls
- # back and uses v0.
+ # back to previous versions.
test_commit -C http_child three &&
@@ -489,10 +489,8 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' '
git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s client_branch >expect &&
test_cmp expect actual &&
- # Client didnt request to use protocol v2
- ! grep "Git-Protocol: version=2" log &&
- # Server didnt respond using protocol v2
- ! grep "git< version 2" log
+ # Server responded with version 1
+ grep "git< version 1" log
'
diff --git a/transport-helper.c b/transport-helper.c
index 143ca008c8..ac1937f1e1 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -105,6 +105,7 @@ static struct child_process *get_helper(struct transport *transport)
{
struct helper_data *data = transport->data;
struct strbuf buf = STRBUF_INIT;
+ struct strbuf version_advert = STRBUF_INIT;
struct child_process *helper;
int duped;
int code;
@@ -127,6 +128,11 @@ static struct child_process *get_helper(struct transport *transport)
argv_array_pushf(&helper->env_array, "%s=%s",
GIT_DIR_ENVIRONMENT, get_git_dir());
+ get_client_protocol_version_advertisement(&version_advert);
+ if (version_advert.len > 0)
+ argv_array_pushf(&helper->env_array, "%s=%s",
+ GIT_PROTOCOL_ENVIRONMENT, version_advert.buf);
+
code = start_command(helper);
if (code < 0 && errno == ENOENT)
die(_("unable to find remote helper for '%s'"), data->name);
--
2.20.1.415.g653613c723-goog
^ permalink raw reply related
* [PATCH v6 0/1] Advertise multiple supported proto versions
From: Josh Steadmon @ 2018-12-20 21:58 UTC (permalink / raw)
To: git
In-Reply-To: <cover.1538516853.git.steadmon@google.com>
Add a registry of supported wire protocol versions that individual
commands can use to declare supported versions before contacting a
server. The client will then advertise all supported versions, while the
server will choose the first allowed version from the advertised
list.
Every command that acts as a client or server must now register its
supported protocol versions.
Changes since V4: remove special cases around advertising version=0.
Changes since V5: no code changes, but corrected and clarified commit
message regarding changes around advertising version=0.
Josh Steadmon (1):
protocol: advertise multiple supported versions
builtin/archive.c | 3 +
builtin/clone.c | 4 ++
builtin/fetch-pack.c | 4 ++
builtin/fetch.c | 5 ++
builtin/ls-remote.c | 5 ++
builtin/pull.c | 5 ++
builtin/push.c | 4 ++
builtin/receive-pack.c | 3 +
builtin/send-pack.c | 3 +
builtin/upload-archive.c | 3 +
builtin/upload-pack.c | 4 ++
connect.c | 52 +++++++--------
protocol.c | 122 +++++++++++++++++++++++++++++++++---
protocol.h | 23 ++++++-
remote-curl.c | 27 +++++---
t/t5551-http-fetch-smart.sh | 1 +
t/t5570-git-daemon.sh | 2 +-
t/t5601-clone.sh | 38 +++++------
t/t5700-protocol-v1.sh | 8 +--
t/t5702-protocol-v2.sh | 16 +++--
transport-helper.c | 6 ++
21 files changed, 256 insertions(+), 82 deletions(-)
Range-diff against v5:
1: 60f6f2fbd8 ! 1: 10039ca163 protocol: advertise multiple supported versions
@@ -22,10 +22,12 @@
select the first allowed version from this advertisement.
Additionally, remove special cases around advertising version=0.
- Previously we avoided adding version negotiation fields in server
- responses if it looked like the client wanted v0. However, including
- these fields does not change behavior, so it's better to have simpler
- code.
+ Previously we avoided adding version advertisements to the client's
+ initial connection request if the client wanted version=0. However,
+ including these advertisements does not change the version negotiation
+ behavior, so it's better to have simpler code. As a side effect, this
+ means that client operations over SSH will always include a
+ "SendEnv=GIT_PROTOCOL" option on the SSH command line.
While we're at it, remove unnecessary externs from function declarations
in protocol.h.
--
2.20.1.415.g653613c723-goog
^ permalink raw reply
* [PATCH 2/2] Rebase: Run post-checkout hook on checkout
From: orgads @ 2018-12-20 21:55 UTC (permalink / raw)
To: git; +Cc: Orgad Shaneh
In-Reply-To: <20181220215559.22454-1-orgads@gmail.com>
From: Orgad Shaneh <orgads@gmail.com>
Signed-off-by: Orgad Shaneh <orgads@gmail.com>
---
builtin/rebase.c | 8 +++++++-
t/t5403-post-checkout-hook.sh | 18 ++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/builtin/rebase.c b/builtin/rebase.c
index b5c99ec10c..78a09dcda2 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -530,6 +530,7 @@ static int run_specific_rebase(struct rebase_options *opts)
#define RESET_HEAD_DETACH (1<<0)
#define RESET_HEAD_HARD (1<<1)
+#define RESET_HEAD_RUN_HOOK (1<<2)
static int reset_head(struct object_id *oid, const char *action,
const char *switch_to_branch, unsigned flags,
@@ -537,6 +538,7 @@ static int reset_head(struct object_id *oid, const char *action,
{
unsigned detach_head = flags & RESET_HEAD_DETACH;
unsigned reset_hard = flags & RESET_HEAD_HARD;
+ unsigned run_hook = flags & RESET_HEAD_RUN_HOOK;
struct object_id head_oid;
struct tree_desc desc[2] = { { NULL }, { NULL } };
struct lock_file lock = LOCK_INIT;
@@ -636,6 +638,10 @@ static int reset_head(struct object_id *oid, const char *action,
ret = update_ref(reflog_head, "HEAD", oid, NULL, 0,
UPDATE_REFS_MSG_ON_ERR);
}
+ if (run_hook)
+ run_hook_le(NULL, "post-checkout",
+ oid_to_hex(orig ? orig : &null_oid),
+ oid_to_hex(oid), "1", NULL);
leave_reset_head:
strbuf_release(&msg);
@@ -1539,7 +1545,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
strbuf_addf(&msg, "%s: checkout %s",
getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
if (reset_head(&options.onto->object.oid, "checkout", NULL,
- RESET_HEAD_DETACH, NULL, msg.buf))
+ RESET_HEAD_DETACH | RESET_HEAD_RUN_HOOK, NULL, msg.buf))
die(_("Could not detach HEAD"));
strbuf_release(&msg);
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 868d6f7272..ed4cc6e945 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -9,6 +9,8 @@ test_description='Test the post-checkout hook.'
test_expect_success setup '
test_commit one &&
test_commit two &&
+ test_commit rebase-on-me &&
+ git reset --hard HEAD^ &&
test_commit three three &&
mv .git/hooks-disabled .git/hooks
'
@@ -52,6 +54,22 @@ test_expect_success 'post-checkout receives the right args when not switching br
test $old = $new && test $flag = 0
'
+test_expect_success 'post-checkout is triggered on rebase' '
+ git checkout -b rebase-test master &&
+ rm -f .git/post-checkout.args &&
+ git rebase rebase-on-me &&
+ read old new flag < .git/post-checkout.args &&
+ test $old != $new && test $flag = 1
+'
+
+test_expect_success 'post-checkout is triggered on rebase with fast-forward' '
+ git checkout -b ff-rebase-test rebase-on-me^ &&
+ rm -f .git/post-checkout.args &&
+ git rebase rebase-on-me &&
+ read old new flag < .git/post-checkout.args &&
+ test $old != $new && test $flag = 1
+'
+
if test "$(git config --bool core.filemode)" = true; then
mkdir -p templates/hooks
cat >templates/hooks/post-checkout <<'EOF'
--
2.20.1
^ permalink raw reply related
* [PATCH 1/2] t5403: Refactor
From: orgads @ 2018-12-20 21:55 UTC (permalink / raw)
To: git; +Cc: Orgad Shaneh
From: Orgad Shaneh <orgads@gmail.com>
* Replace multiple clones and commits by test_commits.
* Replace 3 invocations of awk by read.
Signed-off-by: Orgad Shaneh <orgads@gmail.com>
---
t/t5403-post-checkout-hook.sh | 55 ++++++++++++-----------------------
1 file changed, 18 insertions(+), 37 deletions(-)
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index fc898c9eac..868d6f7272 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,67 +7,48 @@ test_description='Test the post-checkout hook.'
. ./test-lib.sh
test_expect_success setup '
- echo Data for commit0. >a &&
- echo Data for commit0. >b &&
- git update-index --add a &&
- git update-index --add b &&
- tree0=$(git write-tree) &&
- commit0=$(echo setup | git commit-tree $tree0) &&
- git update-ref refs/heads/master $commit0 &&
- git clone ./. clone1 &&
- git clone ./. clone2 &&
- GIT_DIR=clone2/.git git branch new2 &&
- echo Data for commit1. >clone2/b &&
- GIT_DIR=clone2/.git git add clone2/b &&
- GIT_DIR=clone2/.git git commit -m new2
+ test_commit one &&
+ test_commit two &&
+ test_commit three three &&
+ mv .git/hooks-disabled .git/hooks
'
-for clone in 1 2; do
- cat >clone${clone}/.git/hooks/post-checkout <<'EOF'
+cat >.git/hooks/post-checkout <<'EOF'
#!/bin/sh
-echo $@ > $GIT_DIR/post-checkout.args
+echo $@ > .git/post-checkout.args
EOF
- chmod u+x clone${clone}/.git/hooks/post-checkout
-done
+chmod u+x .git/hooks/post-checkout
test_expect_success 'post-checkout runs as expected ' '
- GIT_DIR=clone1/.git git checkout master &&
- test -e clone1/.git/post-checkout.args
+ git checkout master &&
+ test -e .git/post-checkout.args
'
test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' '
- old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout runs as expected ' '
- GIT_DIR=clone1/.git git checkout master &&
- test -e clone1/.git/post-checkout.args
+ git checkout master &&
+ test -e .git/post-checkout.args
'
test_expect_success 'post-checkout args are correct with git checkout -b ' '
- GIT_DIR=clone1/.git git checkout -b new1 &&
- old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ git checkout -b new1 &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args with HEAD changed ' '
- GIT_DIR=clone2/.git git checkout new2 &&
- old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ git checkout two &&
+ read old new flag < .git/post-checkout.args &&
test $old != $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args when not switching branches ' '
- GIT_DIR=clone2/.git git checkout master b &&
- old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ git checkout master -- three &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 0
'
--
2.20.1
^ permalink raw reply related
* [PATCH 2/2] Rebase: Run post-checkout hook on checkout
From: orgads @ 2018-12-20 21:48 UTC (permalink / raw)
To: git; +Cc: Orgad Shaneh
In-Reply-To: <20181220214823.21378-1-orgads@gmail.com>
From: Orgad Shaneh <orgads@gmail.com>
Signed-off-by: Orgad Shaneh <orgads@gmail.com>
---
builtin/rebase.c | 8 +++++++-
t/t5403-post-checkout-hook.sh | 18 ++++++++++++++++++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/builtin/rebase.c b/builtin/rebase.c
index b5c99ec10c..78a09dcda2 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -530,6 +530,7 @@ static int run_specific_rebase(struct rebase_options *opts)
#define RESET_HEAD_DETACH (1<<0)
#define RESET_HEAD_HARD (1<<1)
+#define RESET_HEAD_RUN_HOOK (1<<2)
static int reset_head(struct object_id *oid, const char *action,
const char *switch_to_branch, unsigned flags,
@@ -537,6 +538,7 @@ static int reset_head(struct object_id *oid, const char *action,
{
unsigned detach_head = flags & RESET_HEAD_DETACH;
unsigned reset_hard = flags & RESET_HEAD_HARD;
+ unsigned run_hook = flags & RESET_HEAD_RUN_HOOK;
struct object_id head_oid;
struct tree_desc desc[2] = { { NULL }, { NULL } };
struct lock_file lock = LOCK_INIT;
@@ -636,6 +638,10 @@ static int reset_head(struct object_id *oid, const char *action,
ret = update_ref(reflog_head, "HEAD", oid, NULL, 0,
UPDATE_REFS_MSG_ON_ERR);
}
+ if (run_hook)
+ run_hook_le(NULL, "post-checkout",
+ oid_to_hex(orig ? orig : &null_oid),
+ oid_to_hex(oid), "1", NULL);
leave_reset_head:
strbuf_release(&msg);
@@ -1539,7 +1545,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
strbuf_addf(&msg, "%s: checkout %s",
getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
if (reset_head(&options.onto->object.oid, "checkout", NULL,
- RESET_HEAD_DETACH, NULL, msg.buf))
+ RESET_HEAD_DETACH | RESET_HEAD_RUN_HOOK, NULL, msg.buf))
die(_("Could not detach HEAD"));
strbuf_release(&msg);
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 7e941537f9..de9c7fb871 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -9,6 +9,8 @@ test_description='Test the post-checkout hook.'
test_expect_success setup '
test_commit one &&
test_commit two &&
+ test_commit rebase-on-me &&
+ git reset --hard HEAD^ &&
test_commit three three &&
mv .git/hooks-disabled .git/hooks
'
@@ -52,6 +54,22 @@ test_expect_success 'post-checkout receives the right args when not switching br
test $old = $new && test $flag = 0
'
+test_expect_success 'post-checkout is triggered on rebase' '
+ git checkout -b rebase-test master &&
+ rm -f .git/post-checkout.args &&
+ git rebase rebase-on-me &&
+ read old new flag < .git/post-checkout.args &&
+ test $old != $new && test $flag = 1
+'
+
+test_expect_success 'post-checkout is triggered on rebase with fast-forward' '
+ git checkout -b ff-rebase-test rebase-on-me^ &&
+ rm -f .git/post-checkout.args &&
+ git rebase rebase-on-me &&
+ read old new flag < .git/post-checkout.args &&
+ test $old != $new && test $flag = 1
+'
+
if test "$(git config --bool core.filemode)" = true; then
mkdir -p templates/hooks
cat >templates/hooks/post-checkout <<'EOF'
--
2.20.1
^ permalink raw reply related
* [PATCH 1/2] t5403: Refactor
From: orgads @ 2018-12-20 21:48 UTC (permalink / raw)
To: git; +Cc: Orgad Shaneh
From: Orgad Shaneh <orgads@gmail.com>
* Replace multiple clones and commits by test_commits.
* Replace 3 invocations of awk by read.
Signed-off-by: Orgad Shaneh <orgads@gmail.com>
---
t/t5403-post-checkout-hook.sh | 55 ++++++++++++-----------------------
1 file changed, 18 insertions(+), 37 deletions(-)
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index fc898c9eac..7e941537f9 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,67 +7,48 @@ test_description='Test the post-checkout hook.'
. ./test-lib.sh
test_expect_success setup '
- echo Data for commit0. >a &&
- echo Data for commit0. >b &&
- git update-index --add a &&
- git update-index --add b &&
- tree0=$(git write-tree) &&
- commit0=$(echo setup | git commit-tree $tree0) &&
- git update-ref refs/heads/master $commit0 &&
- git clone ./. clone1 &&
- git clone ./. clone2 &&
- GIT_DIR=clone2/.git git branch new2 &&
- echo Data for commit1. >clone2/b &&
- GIT_DIR=clone2/.git git add clone2/b &&
- GIT_DIR=clone2/.git git commit -m new2
+ test_commit one &&
+ test_commit two &&
+ test_commit three three &&
+ mv .git/hooks-disabled .git/hooks
'
-for clone in 1 2; do
- cat >clone${clone}/.git/hooks/post-checkout <<'EOF'
+cat >.git/hooks/post-checkout <<'EOF'
#!/bin/sh
-echo $@ > $GIT_DIR/post-checkout.args
+echo $@ > .git/post-checkout.args
EOF
- chmod u+x clone${clone}/.git/hooks/post-checkout
-done
+chmod u+x .git/hooks/post-checkout
test_expect_success 'post-checkout runs as expected ' '
- GIT_DIR=clone1/.git git checkout master &&
- test -e clone1/.git/post-checkout.args
+ git checkout master &&
+ test -e .git/post-checkout.args
'
test_expect_success 'post-checkout receives the right arguments with HEAD unchanged ' '
- old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout runs as expected ' '
- GIT_DIR=clone1/.git git checkout master &&
- test -e clone1/.git/post-checkout.args
+ git checkout master &&
+ test -e .git/post-checkout.args
'
test_expect_success 'post-checkout args are correct with git checkout -b ' '
- GIT_DIR=clone1/.git git checkout -b new1 &&
- old=$(awk "{print \$1}" clone1/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone1/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone1/.git/post-checkout.args) &&
+ git checkout -b new1 &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args with HEAD changed ' '
- GIT_DIR=clone2/.git git checkout new2 &&
- old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ git checkout two &&
+ read old new flag < .git/post-checkout.args &&
test $old != $new && test $flag = 1
'
test_expect_success 'post-checkout receives the right args when not switching branches ' '
- GIT_DIR=clone2/.git git checkout master b &&
- old=$(awk "{print \$1}" clone2/.git/post-checkout.args) &&
- new=$(awk "{print \$2}" clone2/.git/post-checkout.args) &&
- flag=$(awk "{print \$3}" clone2/.git/post-checkout.args) &&
+ git checkout master -- three &&
+ read old new flag < .git/post-checkout.args &&
test $old = $new && test $flag = 0
'
--
2.20.1
^ permalink raw reply related
* Re: [PATCH] diff: add support for reading files literally with --no-index
From: Ævar Arnfjörð Bjarmason @ 2018-12-20 21:43 UTC (permalink / raw)
To: brian m. carlson; +Cc: git, Jeff King, Duy Nguyen, Dennis Kaarsemaker
In-Reply-To: <20181220002610.43832-1-sandals@crustytoothpaste.net>
On Thu, Dec 20 2018, brian m. carlson wrote:
> We don't include a test for the pipe scenario because I couldn't get
> that case to work in portable shell (although of course it works in
> bash). I have, however, tested it on both macOS and Linux. No clue how
> this works on Windows.
You can (and should) add tests using the PROCESS_SUBSTITUTION prereq
Dennis used in an earlier version of this:
https://public-inbox.org/git/20170113102021.6054-3-dennis@kaarsemaker.net/
Even if that wasn't possible a bash-specific test is better than no
test, and can be had by including t/lib-bash.sh in your test, see
e.g. the completion tests.
^ permalink raw reply
* Re: rebase: Ask before doing anything not undoable
From: Thomas Braun @ 2018-12-20 21:37 UTC (permalink / raw)
To: Ricardo Biehl Pasquali, Kevin Daudt; +Cc: git
In-Reply-To: <20181220211147.GA7426@localhost.localdomain>
Am 20.12.2018 um 22:11 schrieb Ricardo Biehl Pasquali:
> Ccing the mailing list.
>
> On Thu, Dec 20, 2018 at 07:26:53PM +0100, Kevin Daudt wrote:
>> It would be anoying for users to have to constantly confirm when they
>> run git rebase --continue. Rather than asking confirmation, it would be
>> better to make it easy to go back to the previous state.
>
> I meant confirmation for --committer-date-is-author-date
> option.
>
> As Thomas said, it should be possible to undo the action
> using reflog, although this seems not as easy as it should
> be yet.
The git rebase documentation has
ORIG_HEAD is set to point at the tip of the branch before the reset.
so doing
git reset ORIG_HEAD
does reset to the state before the rebase.
For avoiding the original problem of --co completing to
--committer-date-is-author-date I'm using the alias rc for git rebase
--continue.
^ permalink raw reply
* Re: rebase: Ask before doing anything not undoable
From: Ricardo Biehl Pasquali @ 2018-12-20 21:11 UTC (permalink / raw)
To: Kevin Daudt; +Cc: git
In-Reply-To: <20181220182653.GB4823@alpha>
Ccing the mailing list.
On Thu, Dec 20, 2018 at 07:26:53PM +0100, Kevin Daudt wrote:
> It would be anoying for users to have to constantly confirm when they
> run git rebase --continue. Rather than asking confirmation, it would be
> better to make it easy to go back to the previous state.
I meant confirmation for --committer-date-is-author-date
option.
As Thomas said, it should be possible to undo the action
using reflog, although this seems not as easy as it should
be yet.
pasquali
^ permalink raw reply
* Re: [PATCH v4 0/3] Add commit-graph fuzzer and fix buffer overflow
From: Jeff King @ 2018-12-20 20:11 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, gitster, stolee, avarab, szeder.dev
In-Reply-To: <nycvar.QRO.7.76.6.1812202034390.41@tvgsbejvaqbjf.bet>
On Thu, Dec 20, 2018 at 08:35:57PM +0100, Johannes Schindelin wrote:
> > I do wonder if we'll run into problems on Windows, though.
>
> As long as we're talking about Unix shell scripts, /dev/zero should be
> fine, as we are essentially running in a variant of Cygwin.
>
> If you try to pass /dev/zero as an argument to a Git command, that's an
> entirely different thing: this most likely won't work.
Thanks for confirming. We're talking about passing it to dd here, so I
think it should be OK.
-Peff
^ permalink raw reply
* Unable to install latest git version. Claims git process pid running
From: David Brown @ 2018-12-20 20:03 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 1896 bytes --]
- [ ] I was not able to find an
[open](https://github.com/git-for-windows/git/issues?q=is%3Aopen) or
[closed](https://github.com/git-for-windows/git/issues?q=is%3Aclosed)
issue matching what I'm seeing
### Setup
- Which version of Git for Windows are you using? Is it 32-bit or
64-bit?
$ git --version --build-options
git version 2.20.0.windows.1 cpu: x86_64 built from commit:
95155834166f64fe9666f2c0a4909f076080893a
sizeof-long: 4
sizeof-size_t: 8 **
- Which version of Windows are you running? Vista, 7, 8, 10? Is it
32-bit or 64-bit?
$ cmd.exe /c ver
** Microsoft Windows [Version 6.1.7601] **
- What options did you set as part of the installation? Or did you
choose the
defaults?
# One of the following:
$ cat /etc/install-options.txt Editor Option: VIM Custom Editor Path:
Path Option: BashOnly
SSH Option: OpenSSH
CURL Option: WinSSL
CRLF Option: CRLFAlways
Bash Terminal Option: MinTTY
Performance Tweaks
FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Disabled
- Any other interesting things about your environment that might be
related
to the issue you're seeing?
** A so-called VDI running on a Dell WYSE **
### Details
- Which terminal/shell are you running Git from? e.g
Bash/CMD/PowerShell/other
** Bash **
- What commands did you run to trigger this issue? If you can provide a
[Minimal, Complete, and Verifiable
example](http://stackoverflow.com/help/mcve)
this will help us understand the issue.
** Windows git upgrade dialog **
- What did you expect to occur after running these commands?
** latest version of git installed **
- What actually happened instead?
** No such pid 10128 to close therefore cancel install **
- If the probleminsert URL herey, can you provide the
URL to that repository to help us with testing?
** Internal company url. Windows git install dialog is issue **
[-- Attachment #2: git_pid10128.PNG --]
[-- Type: image/png, Size: 22622 bytes --]
^ permalink raw reply
* Incorrect tree shown with ls-tree ref^{type}:{{folder}}
From: Stan Hu @ 2018-12-20 20:05 UTC (permalink / raw)
To: git
Suppose I have a repository that has the following files:
foo/bar/test1.txt
foo/{{curly}}/test2.txt
The following works fine:
$ git ls-tree master^{tree}
040000 tree 9284ac5fef7ad99a2bd508a8c89bde8bd1a88e9f foo
$ git ls-tree master^{tree}:foo
040000 tree 69497de4d9a72713f87df8280a147e0a597c4055 bar
040000 tree b2abdac384f111c1a8a518e05b963a3bb2541659 {{curly}}
$ git ls-tree master^{tree}:foo/bar
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 test1.txt
$ git ls-tree master:foo/{{curly}}
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 test2.txt
However, the following returns the root tree instead of the tree
belonging to {{curly}}:
$ git ls-tree master^{tree}:foo/{{curly}}
040000 tree 9284ac5fef7ad99a2bd508a8c89bde8bd1a88e9f foo
I believe the problem is on this line in sha1-name.c:peel_onion()
(https://github.com/git/git/blob/b21ebb671bb7dea8d342225f0d66c41f4e54d5ca/sha1-name.c#L1004):
if (len < 4 || name[len-1] != '}')
Since name is "master^{tree}:foo/{{curly}}", peel_onion() returns
early, thinking it is done.
I can append a '/' to force peel_onion() to work, but is that the
right thing to do here? Should this condition handle the
"ref^{type}:filename" case properly?
^ 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