Git development
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/2] tree:<depth>: skip some trees even when collecting omits
From: Jonathan Tan @ 2019-01-08 23:22 UTC (permalink / raw)
  To: jonathantanmy
  Cc: matvore, git, sbeller, git, jeffhost, peff, stefanbeller, pclouds
In-Reply-To: <20190108020034.23648-1-jonathantanmy@google.com>

> > -static void filter_trees_update_omits(
> > +static int filter_trees_update_omits(
> >  	struct object *obj,
> >  	struct filter_trees_depth_data *filter_data,
> >  	int include_it)
> >  {
> >  	if (!filter_data->omits)
> > -		return;
> > +		return 1;
> >  
> >  	if (include_it)
> > -		oidset_remove(filter_data->omits, &obj->oid);
> > +		return oidset_remove(filter_data->omits, &obj->oid);
> >  	else
> > -		oidset_insert(filter_data->omits, &obj->oid);
> > +		return oidset_insert(filter_data->omits, &obj->oid);
> >  }
> 
> I think this function is getting too magical - if filter_data->omits is
> not set, we pretend that we have omitted the tree, because we want the
> same behavior when not needing omits and when the tree is omitted. Could
> this be done another way?

Giving some more thought to this, since this is a static function, maybe
documenting it as "Returns 1 if the objects that this object references need to
be traversed for "omits" updates, and 0 otherwise" (with the appropriate code
updates) would suffice.

^ permalink raw reply

* Re: [PATCH v2 1/2] list-objects-filter: teach tree:# how to handle >0
From: Jonathan Tan @ 2019-01-08 23:19 UTC (permalink / raw)
  To: matvore
  Cc: jonathantanmy, matvore, git, sbeller, git, jeffhost, peff,
	stefanbeller, pclouds
In-Reply-To: <54fba0d3-4b8e-1faf-4b2d-e67c1f5fbf02@comcast.net>

> > Any reason for moving "case LOFS_BLOB" (and "case LOFS_BEGIN_TREE"
> > below) after LOFS_END_TREE?
> 
> I put LOFS_BLOB and after LOFS_END_TREE since that is the order in all 
> the other filter logic functions. I put LOFS_BEGIN_TREE at the end 
> (which is different from the other filter logic functions) because it's 
> usually better to put simpler things before longer or more complex 
> things. LOFS_BEGIN_TREE is much more complex and if it were not the last 
> switch section, it would tend to hide the sections that come after it.
> 
> FWIW, I consider this the coding corollary of the end-weight problem in 
> linguistics - see https://www.thoughtco.com/end-weight-grammar-1690594 - 
> this is not my original idea, but something from the book Perl Best 
> Practices, although that book only mentioned it in the context of 
> ordering clauses in single statements rather than ordering entire blocks.

OK - my thinking was that we should minimize the diff, but this
reasoning makes sense to me.

> > Here, filter_trees_update_omits() is
> > only ever used to remove a blob from the omits set, since once this blob
> > is encountered with include_it == true, it is marked as LOFR_MARK_SEEN
> > and will not be traversed again.
> It is possible that include_it can be false and then in a later 
> invocation it can be true. In that case, the blob will be added to the 
> set and then removed from it.

Ah...yes, you're right.

> For your reference, here is an interdiff for this particular patch after 
> applying your comments:

The interdiff looks good, thanks. All my issues are resolved.

^ permalink raw reply

* Re: [PATCH] log: add %S option (like --source) to log --format
From: Junio C Hamano @ 2019-01-08 22:21 UTC (permalink / raw)
  To: issac.trotts; +Cc: git, noemi, Issac Trotts
In-Reply-To: <20190108132048.57142-1-issactrotts@google.com>

issac.trotts@gmail.com writes:

> From: Issac Trotts <issac.trotts@gmail.com>

Heh, I'll edit this line to match S-o-b: below.

>
> 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>
>
> ---



> 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;

There are quite a few existing codepaths that change their behaviour
based on NULL-ness of ctx.rev field.  How would we make sure that
this change have no unintended consequence, I wonder?

> +	case 'S':		/* tag/branch like --source */
> +		if (c->pretty_ctx->rev == NULL || c->pretty_ctx->rev->sources == NULL) {
> +			return 0;
> +		}
> +		slot = revision_sources_at(c->pretty_ctx->rev->sources, commit);
> +		if (!(slot && *slot)) {
> +			return 0;
> +		}
> +		strbuf_addstr(sb, *slot);
> +		return 1;

Let's update the style of this hunk here like so:

	if (!c->pretty_ctx->rev || !c->pretty_ctx->rev->sources)
		return 0;
	slot = ...;
	if (!(slot && *slot))
		return 0;
	strbuf_addstr(...);
	return 1;

I wonder if it is even better to apply de-Morgan to one of the above
two, i.e.

	if (!(c->pretty_ctx->rev && c->pretty_ctx->rev->sources))
		return 0;


Anyway, thanks.  Will queue.


^ permalink raw reply

* Regression: submodule worktrees can clobber core.worktree config
From: Tomasz Śniatowski @ 2019-01-08 22:16 UTC (permalink / raw)
  To: git

After upgrading to 2.20.1 I noticed in some submodule+worktree scenarios git
will break the submodule configuration. Reproducible with:
    git init a && (cd a; touch a; git add a; git commit -ma)
    git init b && (cd b; git submodule add ../a; git commit -mb)
    git -C b worktree add ../b2
    git -C b/a worktree add ../../b2/a
    git -C b status
    git -C b2 submodule update
    git -C b status

The submodule update in the _worktree_ puts an invalid core.worktree value in
the _original_ repository submodule config (b/.git/modules/a/config), causing
the last git status to error out with:
    fatal: cannot chdir to '../../../../../../b2/a': No such file or directory
    fatal: 'git status --porcelain=2' failed in submodule a

Looking at the config file itself, the submodule update operation applies the
following change (the new path is invalid):
    -       worktree = ../../../a
    +       worktree = ../../../../../../b2/a

This worked fine on 2.19.2 (no config change, no error), and was useful to have
a worktree with (large) submodules that are also worktrees.

Bisects down to:
74d4731da1 submodule--helper: replace connect-gitdir-workingtree by
ensure-core-worktree

--
Tomasz Śniatowski

^ permalink raw reply

* [PATCH v3 8/8] checkout: introduce checkout.overlayMode config
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

In the previous patch we introduced a new no-overlay mode for git
checkout.  Some users (such as the author of this commit) may want to
have this mode turned on by default as it matches their mental model
more closely.  Make that possible by introducing a new config option
to that extend.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/config/checkout.txt |  7 +++++++
 builtin/checkout.c                |  8 +++++++-
 t/t2025-checkout-no-overlay.sh    | 10 ++++++++++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/Documentation/config/checkout.txt b/Documentation/config/checkout.txt
index c4118fa196..73380a8d86 100644
--- a/Documentation/config/checkout.txt
+++ b/Documentation/config/checkout.txt
@@ -21,3 +21,10 @@ checkout.optimizeNewBranch::
 	will not update the skip-worktree bit in the index nor add/remove
 	files in the working directory to reflect the current sparse checkout
 	settings nor will it show the local changes.
+
+checkout.overlayMode::
+	In the default overlay mode, `git checkout` never
+	removes files from the index or the working tree.  When
+	setting `checkout.overlayMode` to false, files that appear in
+	the index and working tree, but not in <tree-ish> are removed,
+	to make them match <tree-ish> exactly.
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 0c5fe948ef..b5dfc45736 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1019,13 +1019,19 @@ static int switch_branches(const struct checkout_opts *opts,
 
 static int git_checkout_config(const char *var, const char *value, void *cb)
 {
+	struct checkout_opts *opts = cb;
+
 	if (!strcmp(var, "checkout.optimizenewbranch")) {
 		checkout_optimize_new_branch = git_config_bool(var, value);
 		return 0;
 	}
 
+	if (!strcmp(var, "checkout.overlaymode")) {
+		opts->overlay_mode = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "diff.ignoresubmodules")) {
-		struct checkout_opts *opts = cb;
 		handle_ignore_submodules_arg(&opts->diff_options, value);
 		return 0;
 	}
diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh
index 76330cb5ab..a4912e35cb 100755
--- a/t/t2025-checkout-no-overlay.sh
+++ b/t/t2025-checkout-no-overlay.sh
@@ -44,4 +44,14 @@ test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
 	test_path_is_missing file1
 '
 
+test_expect_success 'checkout with checkout.overlayMode=false deletes files not in <tree-ish>' '
+	>file &&
+	mkdir dir &&
+	>dir/file1 &&
+	git add file dir/file1 &&
+	git -c checkout.overlayMode=false checkout HEAD -- file &&
+	test_path_is_missing file &&
+	test_path_is_file dir/file1
+'
+
 test_done
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 7/8] checkout: introduce --{,no-}overlay option
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

Currently 'git checkout' is defined as an overlay operation, which
means that if in 'git checkout <tree-ish> -- [<pathspec>]' we have an
entry in the index that matches <pathspec>, but that doesn't exist in
<tree-ish>, that entry will not be removed from the index or the
working tree.

Introduce a new --{,no-}overlay option, which allows using 'git
checkout' in non-overlay mode, thus removing files from the working
tree if they do not exist in <tree-ish> but match <pathspec>.

Note that 'git checkout -p <tree-ish> -- [<pathspec>]' already works
this way, so no changes are needed for the patch mode.  We disallow
'git checkout --overlay -p' to avoid confusing users who would expect
to be able to force overlay mode in 'git checkout -p' this way.

Untracked files are not affected by this change, so 'git checkout
--no-overlay HEAD -- untracked' will not remove untracked from the
working tree.  This is so e.g. 'git checkout --no-overlay HEAD -- dir/'
doesn't delete all untracked files in dir/, but rather just resets the
state of files that are known to git.

Suggested-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/git-checkout.txt | 10 ++++++
 builtin/checkout.c             | 66 +++++++++++++++++++++++++++++-----
 t/t2025-checkout-no-overlay.sh | 47 ++++++++++++++++++++++++
 t/t9902-completion.sh          |  1 +
 4 files changed, 116 insertions(+), 8 deletions(-)
 create mode 100755 t/t2025-checkout-no-overlay.sh

diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 801de2f764..24e52b01e1 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -260,6 +260,9 @@ the conflicted merge in the specified paths.
 This means that you can use `git checkout -p` to selectively discard
 edits from your current working tree. See the ``Interactive Mode''
 section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
++
+Note that this option uses the no overlay mode by default (see also
+`--[no-]overlay`), and currently doesn't support overlay mode.
 
 --ignore-other-worktrees::
 	`git checkout` refuses when the wanted ref is already checked
@@ -276,6 +279,13 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
 	Just like linkgit:git-submodule[1], this will detach the
 	submodules HEAD.
 
+--[no-]overlay::
+	In the default overlay mode, `git checkout` never
+	removes files from the index or the working tree.  When
+	specifying `--no-overlay`, files that appear in the index and
+	working tree, but not in <tree-ish> are removed, to make them
+	match <tree-ish> exactly.
+
 <branch>::
 	Branch to checkout; if it refers to a branch (i.e., a name that,
 	when prepended with "refs/heads/", is a valid ref), then that
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 32c4b7f897..0c5fe948ef 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -44,6 +44,7 @@ struct checkout_opts {
 	int ignore_skipworktree;
 	int ignore_other_worktrees;
 	int show_progress;
+	int overlay_mode;
 	/*
 	 * If new checkout options are added, skip_merge_working_tree
 	 * should be updated accordingly.
@@ -132,7 +133,8 @@ static int skip_same_name(const struct cache_entry *ce, int pos)
 	return pos;
 }
 
-static int check_stage(int stage, const struct cache_entry *ce, int pos)
+static int check_stage(int stage, const struct cache_entry *ce, int pos,
+		       int overlay_mode)
 {
 	while (pos < active_nr &&
 	       !strcmp(active_cache[pos]->name, ce->name)) {
@@ -140,6 +142,8 @@ static int check_stage(int stage, const struct cache_entry *ce, int pos)
 			return 0;
 		pos++;
 	}
+	if (!overlay_mode)
+		return 0;
 	if (stage == 2)
 		return error(_("path '%s' does not have our version"), ce->name);
 	else
@@ -165,7 +169,7 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
 }
 
 static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
-			  const struct checkout *state)
+			  const struct checkout *state, int overlay_mode)
 {
 	while (pos < active_nr &&
 	       !strcmp(active_cache[pos]->name, ce->name)) {
@@ -173,6 +177,10 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
 			return checkout_entry(active_cache[pos], state, NULL);
 		pos++;
 	}
+	if (!overlay_mode) {
+		unlink_entry(ce);
+		return 0;
+	}
 	if (stage == 2)
 		return error(_("path '%s' does not have our version"), ce->name);
 	else
@@ -247,9 +255,9 @@ static int checkout_merged(int pos, const struct checkout *state)
 	return status;
 }
 
-static void mark_ce_for_checkout(struct cache_entry *ce,
-				 char *ps_matched,
-				 const struct checkout_opts *opts)
+static void mark_ce_for_checkout_overlay(struct cache_entry *ce,
+					 char *ps_matched,
+					 const struct checkout_opts *opts)
 {
 	ce->ce_flags &= ~CE_MATCHED;
 	if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
@@ -281,6 +289,25 @@ static void mark_ce_for_checkout(struct cache_entry *ce,
 		ce->ce_flags |= CE_MATCHED;
 }
 
+static void mark_ce_for_checkout_no_overlay(struct cache_entry *ce,
+					    char *ps_matched,
+					    const struct checkout_opts *opts)
+{
+	ce->ce_flags &= ~CE_MATCHED;
+	if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
+		return;
+	if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched)) {
+		ce->ce_flags |= CE_MATCHED;
+		if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
+			/*
+			 * In overlay mode, but the path is not in
+			 * tree-ish, which means we should remove it
+			 * from the index and the working tree.
+			 */
+			ce->ce_flags |= CE_REMOVE | CE_WT_REMOVE;
+	}
+}
+
 static int checkout_paths(const struct checkout_opts *opts,
 			  const char *revision)
 {
@@ -332,7 +359,14 @@ static int checkout_paths(const struct checkout_opts *opts,
 	 * to be checked out.
 	 */
 	for (pos = 0; pos < active_nr; pos++)
-		mark_ce_for_checkout(active_cache[pos], ps_matched, opts);
+		if (opts->overlay_mode)
+			mark_ce_for_checkout_overlay(active_cache[pos],
+						     ps_matched,
+						     opts);
+		else
+			mark_ce_for_checkout_no_overlay(active_cache[pos],
+							ps_matched,
+							opts);
 
 	if (report_path_error(ps_matched, &opts->pathspec, opts->prefix)) {
 		free(ps_matched);
@@ -353,7 +387,7 @@ static int checkout_paths(const struct checkout_opts *opts,
 			if (opts->force) {
 				warning(_("path '%s' is unmerged"), ce->name);
 			} else if (opts->writeout_stage) {
-				errs |= check_stage(opts->writeout_stage, ce, pos);
+				errs |= check_stage(opts->writeout_stage, ce, pos, opts->overlay_mode);
 			} else if (opts->merge) {
 				errs |= check_stages((1<<2) | (1<<3), ce, pos);
 			} else {
@@ -380,12 +414,14 @@ static int checkout_paths(const struct checkout_opts *opts,
 				continue;
 			}
 			if (opts->writeout_stage)
-				errs |= checkout_stage(opts->writeout_stage, ce, pos, &state);
+				errs |= checkout_stage(opts->writeout_stage, ce, pos, &state, opts->overlay_mode);
 			else if (opts->merge)
 				errs |= checkout_merged(pos, &state);
 			pos = skip_same_name(ce, pos) - 1;
 		}
 	}
+	remove_marked_cache_entries(&the_index, 1);
+	remove_scheduled_dirs();
 	errs |= finish_delayed_checkout(&state);
 
 	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
@@ -547,6 +583,11 @@ static int skip_merge_working_tree(const struct checkout_opts *opts,
 	 * opts->show_progress only impacts output so doesn't require a merge
 	 */
 
+	/*
+	 * opts->overlay_mode cannot be used with switching branches so is
+	 * not tested here
+	 */
+
 	/*
 	 * If we aren't creating a new branch any changes or updates will
 	 * happen in the existing branch.  Since that could only be updating
@@ -1183,6 +1224,10 @@ static int checkout_branch(struct checkout_opts *opts,
 		die(_("'%s' cannot be used with switching branches"),
 		    "--patch");
 
+	if (!opts->overlay_mode)
+		die(_("'%s' cannot be used with switching branches"),
+		    "--no-overlay");
+
 	if (opts->writeout_stage)
 		die(_("'%s' cannot be used with switching branches"),
 		    "--ours/--theirs");
@@ -1271,6 +1316,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 			    "checkout", "control recursive updating of submodules",
 			    PARSE_OPT_OPTARG, option_parse_recurse_submodules_worktree_updater },
 		OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
+		OPT_BOOL(0, "overlay", &opts.overlay_mode, N_("use overlay mode (default)")),
 		OPT_END(),
 	};
 
@@ -1279,6 +1325,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	opts.overwrite_ignore = 1;
 	opts.prefix = prefix;
 	opts.show_progress = -1;
+	opts.overlay_mode = -1;
 
 	git_config(git_checkout_config, &opts);
 
@@ -1302,6 +1349,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 	if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
 		die(_("-b, -B and --orphan are mutually exclusive"));
 
+	if (opts.overlay_mode == 1 && opts.patch_mode)
+		die(_("-p and --overlay are mutually exclusive"));
+
 	/*
 	 * From here on, new_branch will contain the branch to be checked out,
 	 * and new_branch_force and new_orphan_branch will tell us which one of
diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh
new file mode 100755
index 0000000000..76330cb5ab
--- /dev/null
+++ b/t/t2025-checkout-no-overlay.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+test_description='checkout --no-overlay <tree-ish> -- <pathspec>'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	git commit --allow-empty -m "initial"
+'
+
+test_expect_success 'checkout --no-overlay deletes files not in <tree-ish>' '
+	>file &&
+	mkdir dir &&
+	>dir/file1 &&
+	git add file dir/file1 &&
+	git checkout --no-overlay HEAD -- file &&
+	test_path_is_missing file &&
+	test_path_is_file dir/file1
+'
+
+test_expect_success 'checkout --no-overlay removing last file from directory' '
+	git checkout --no-overlay HEAD -- dir/file1 &&
+	test_path_is_missing dir
+'
+
+test_expect_success 'checkout -p --overlay is disallowed' '
+	test_must_fail git checkout -p --overlay HEAD 2>actual &&
+	test_i18ngrep "fatal: -p and --overlay are mutually exclusive" actual
+'
+
+test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
+	test_commit file1 file1 &&
+	test_commit file2 file2 &&
+	git rm --cached file1 &&
+	echo 1234 >file1 &&
+	F1=$(git rev-parse HEAD:file1) &&
+	F2=$(git rev-parse HEAD:file2) &&
+	{
+		echo "100644 $F1 1	file1" &&
+		echo "100644 $F2 2	file1"
+	} | git update-index --index-info &&
+	test_path_is_file file1 &&
+	git checkout --theirs --no-overlay -- file1 &&
+	test_path_is_missing file1
+'
+
+test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index d01ad8eb25..5758fffa0d 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1436,6 +1436,7 @@ test_expect_success 'double dash "git checkout"' '
 	--progress Z
 	--no-quiet Z
 	--no-... Z
+	--overlay Z
 	EOF
 '
 
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 6/8] checkout: factor out mark_cache_entry_for_checkout function
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

Factor out the code that marks a cache entry as matched for checkout
into a separate function.  We are going to introduce a new mode in
'git checkout' in a subsequent commit, that is going to have a
slightly different logic.  This would make this code unnecessarily
complex.

Moving that complexity into separate functions will make the code in
the subsequent step easier to follow.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 builtin/checkout.c | 67 +++++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 31 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index cb166b2e07..32c4b7f897 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -247,6 +247,40 @@ static int checkout_merged(int pos, const struct checkout *state)
 	return status;
 }
 
+static void mark_ce_for_checkout(struct cache_entry *ce,
+				 char *ps_matched,
+				 const struct checkout_opts *opts)
+{
+	ce->ce_flags &= ~CE_MATCHED;
+	if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
+		return;
+	if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
+		/*
+		 * "git checkout tree-ish -- path", but this entry
+		 * is in the original index but is not in tree-ish
+		 * or does not match the pathspec; it will not be
+		 * checked out to the working tree.  We will not do
+		 * anything to this entry at all.
+		 */
+		return;
+	/*
+	 * Either this entry came from the tree-ish we are
+	 * checking the paths out of, or we are checking out
+	 * of the index.
+	 *
+	 * If it comes from the tree-ish, we already know it
+	 * matches the pathspec and could just stamp
+	 * CE_MATCHED to it from update_some(). But we still
+	 * need ps_matched and read_tree_recursive (and
+	 * eventually tree_entry_interesting) cannot fill
+	 * ps_matched yet. Once it can, we can avoid calling
+	 * match_pathspec() for _all_ entries when
+	 * opts->source_tree != NULL.
+	 */
+	if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
+		ce->ce_flags |= CE_MATCHED;
+}
+
 static int checkout_paths(const struct checkout_opts *opts,
 			  const char *revision)
 {
@@ -297,37 +331,8 @@ static int checkout_paths(const struct checkout_opts *opts,
 	 * Make sure all pathspecs participated in locating the paths
 	 * to be checked out.
 	 */
-	for (pos = 0; pos < active_nr; pos++) {
-		struct cache_entry *ce = active_cache[pos];
-		ce->ce_flags &= ~CE_MATCHED;
-		if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
-			continue;
-		if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
-			/*
-			 * "git checkout tree-ish -- path" and this entry
-			 * is in the original index, but is not in tree-ish
-			 * or does not match the pathspec; it will not be
-			 * checked out to the working tree.  We will not do
-			 * anything to this entry at all.
-			 */
-			continue;
-		/*
-		 * Either this entry came from the tree-ish we are
-		 * checking the paths out of, or we are checking out
-		 * of the index.
-		 *
-		 * If it comes from the tree-ish, we already know it
-		 * matches the pathspec and could just stamp
-		 * CE_MATCHED to it from update_some(). But we still
-		 * need ps_matched and read_tree_recursive (and
-		 * eventually tree_entry_interesting) cannot fill
-		 * ps_matched yet. Once it can, we can avoid calling
-		 * match_pathspec() for _all_ entries when
-		 * opts->source_tree != NULL.
-		 */
-		if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
-			ce->ce_flags |= CE_MATCHED;
-	}
+	for (pos = 0; pos < active_nr; pos++)
+		mark_ce_for_checkout(active_cache[pos], ps_matched, opts);
 
 	if (report_path_error(ps_matched, &opts->pathspec, opts->prefix)) {
 		free(ps_matched);
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 5/8] checkout: clarify comment
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

The key point for the if statement is that read_tree_some did not
update the entry, because either it doesn't exist in tree-ish or
doesn't match the pathspec.  Clarify that.

Suggested-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 builtin/checkout.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index acdafc6e4c..cb166b2e07 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -304,10 +304,10 @@ static int checkout_paths(const struct checkout_opts *opts,
 			continue;
 		if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
 			/*
-			 * "git checkout tree-ish -- path", but this entry
-			 * is in the original index; it will not be checked
-			 * out to the working tree and it does not matter
-			 * if pathspec matched this entry.  We will not do
+			 * "git checkout tree-ish -- path" and this entry
+			 * is in the original index, but is not in tree-ish
+			 * or does not match the pathspec; it will not be
+			 * checked out to the working tree.  We will not do
 			 * anything to this entry at all.
 			 */
 			continue;
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 3/8] entry: support CE_WT_REMOVE flag in checkout_entry
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

'checkout_entry()' currently only supports creating new entries in the
working tree, but not deleting them.  Add the ability to remove
entries at the same time if the entry is marked with the CE_WT_REMOVE
flag.

Currently this doesn't have any effect, as the CE_WT_REMOVE flag is
only used in unpack-tree, however we will make use of this in a
subsequent step in the series.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 entry.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/entry.c b/entry.c
index b9eef57117..3d3701e7ae 100644
--- a/entry.c
+++ b/entry.c
@@ -441,6 +441,17 @@ int checkout_entry(struct cache_entry *ce,
 	static struct strbuf path = STRBUF_INIT;
 	struct stat st;
 
+	if (ce->ce_flags & CE_WT_REMOVE) {
+		if (topath)
+			/*
+			 * No content and thus no path to create, so we have
+			 * no pathname to return.
+			 */
+			BUG("Can't remove entry to a path");
+		unlink_entry(ce);
+		return 0;
+	}
+
 	if (topath)
 		return write_entry(ce, topath, state, 1);
 
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 4/8] read-cache: add invalidate parameter to remove_marked_cache_entries
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

When marking cache entries for removal, and later removing them all at
once using 'remove_marked_cache_entries()', cache entries currently
have to be invalidated manually in the cache tree and in the untracked
cache.

Add an invalidate flag to the function.  With the flag set, the
function will take care of invalidating the path in the cache tree and
in the untracked cache.

Note that the current callsites already do the invalidation properly
in other places, so we're just passing 0 from there to keep the status
quo.

This will be useful in a subsequent commit.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 cache.h        | 2 +-
 read-cache.c   | 8 +++++++-
 split-index.c  | 2 +-
 unpack-trees.c | 2 +-
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index c1c953e810..1deee48f5b 100644
--- a/cache.h
+++ b/cache.h
@@ -751,7 +751,7 @@ extern void rename_index_entry_at(struct index_state *, int pos, const char *new
 /* Remove entry, return true if there are more entries to go. */
 extern int remove_index_entry_at(struct index_state *, int pos);
 
-extern void remove_marked_cache_entries(struct index_state *istate);
+extern void remove_marked_cache_entries(struct index_state *istate, int invalidate);
 extern int remove_file_from_index(struct index_state *, const char *path);
 #define ADD_CACHE_VERBOSE 1
 #define ADD_CACHE_PRETEND 2
diff --git a/read-cache.c b/read-cache.c
index bd45dc3e24..978d43f676 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -590,13 +590,19 @@ int remove_index_entry_at(struct index_state *istate, int pos)
  * CE_REMOVE is set in ce_flags.  This is much more effective than
  * calling remove_index_entry_at() for each entry to be removed.
  */
-void remove_marked_cache_entries(struct index_state *istate)
+void remove_marked_cache_entries(struct index_state *istate, int invalidate)
 {
 	struct cache_entry **ce_array = istate->cache;
 	unsigned int i, j;
 
 	for (i = j = 0; i < istate->cache_nr; i++) {
 		if (ce_array[i]->ce_flags & CE_REMOVE) {
+			if (invalidate) {
+				cache_tree_invalidate_path(istate,
+							   ce_array[i]->name);
+				untracked_cache_remove_from_index(istate,
+								  ce_array[i]->name);
+			}
 			remove_name_hash(istate, ce_array[i]);
 			save_or_free_index_entry(istate, ce_array[i]);
 		}
diff --git a/split-index.c b/split-index.c
index 5820412dc5..8aebc3661b 100644
--- a/split-index.c
+++ b/split-index.c
@@ -162,7 +162,7 @@ void merge_base_index(struct index_state *istate)
 	ewah_each_bit(si->replace_bitmap, replace_entry, istate);
 	ewah_each_bit(si->delete_bitmap, mark_entry_for_delete, istate);
 	if (si->nr_deletions)
-		remove_marked_cache_entries(istate);
+		remove_marked_cache_entries(istate, 0);
 
 	for (i = si->nr_replacements; i < si->saved_cache_nr; i++) {
 		if (!ce_namelen(si->saved_cache[i]))
diff --git a/unpack-trees.c b/unpack-trees.c
index e8d1a6ac50..8e6afa924d 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -392,7 +392,7 @@ static int check_updates(struct unpack_trees_options *o)
 				unlink_entry(ce);
 		}
 	}
-	remove_marked_cache_entries(index);
+	remove_marked_cache_entries(index, 0);
 	remove_scheduled_dirs();
 
 	if (should_update_submodules() && o->update && !o->dry_run)
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 1/8] move worktree tests to t24*
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

The 'git worktree' command used to be just another mode in 'git
checkout', namely 'git checkout --to'.  When the tests for the latter
were retrofitted for the former, the test name was adjusted, but the
test number was kept, even though the test is testing a different
command now.  t/README states: "Second digit tells the particular
command we are testing.", so 'git worktree' should have a separate
number just for itself.

Move the worktree tests to t24* to adhere to that guideline. We're
going to make use of the free'd up numbers in a subsequent commit.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 t/{t2025-worktree-add.sh => t2400-worktree-add.sh}       | 0
 t/{t2026-worktree-prune.sh => t2401-worktree-prune.sh}   | 0
 t/{t2027-worktree-list.sh => t2402-worktree-list.sh}     | 0
 t/{t2028-worktree-move.sh => t2403-worktree-move.sh}     | 0
 t/{t2029-worktree-config.sh => t2404-worktree-config.sh} | 0
 5 files changed, 0 insertions(+), 0 deletions(-)
 rename t/{t2025-worktree-add.sh => t2400-worktree-add.sh} (100%)
 rename t/{t2026-worktree-prune.sh => t2401-worktree-prune.sh} (100%)
 rename t/{t2027-worktree-list.sh => t2402-worktree-list.sh} (100%)
 rename t/{t2028-worktree-move.sh => t2403-worktree-move.sh} (100%)
 rename t/{t2029-worktree-config.sh => t2404-worktree-config.sh} (100%)

diff --git a/t/t2025-worktree-add.sh b/t/t2400-worktree-add.sh
similarity index 100%
rename from t/t2025-worktree-add.sh
rename to t/t2400-worktree-add.sh
diff --git a/t/t2026-worktree-prune.sh b/t/t2401-worktree-prune.sh
similarity index 100%
rename from t/t2026-worktree-prune.sh
rename to t/t2401-worktree-prune.sh
diff --git a/t/t2027-worktree-list.sh b/t/t2402-worktree-list.sh
similarity index 100%
rename from t/t2027-worktree-list.sh
rename to t/t2402-worktree-list.sh
diff --git a/t/t2028-worktree-move.sh b/t/t2403-worktree-move.sh
similarity index 100%
rename from t/t2028-worktree-move.sh
rename to t/t2403-worktree-move.sh
diff --git a/t/t2029-worktree-config.sh b/t/t2404-worktree-config.sh
similarity index 100%
rename from t/t2029-worktree-config.sh
rename to t/t2404-worktree-config.sh
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply

* [PATCH v3 2/8] entry: factor out unlink_entry function
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20190108215225.3077-1-t.gummerer@gmail.com>

Factor out the 'unlink_entry()' function from unpack-trees.c to
entry.c.  It will be used in other places as well in subsequent
steps.

As it's no longer a static function, also move the documentation to
the header file to make it more discoverable.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 cache.h        |  5 +++++
 entry.c        | 15 +++++++++++++++
 unpack-trees.c | 19 -------------------
 3 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/cache.h b/cache.h
index ca36b44ee0..c1c953e810 100644
--- a/cache.h
+++ b/cache.h
@@ -1542,6 +1542,11 @@ struct checkout {
 extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
 extern void enable_delayed_checkout(struct checkout *state);
 extern int finish_delayed_checkout(struct checkout *state);
+/*
+ * Unlink the last component and schedule the leading directories for
+ * removal, such that empty directories get removed.
+ */
+extern void unlink_entry(const struct cache_entry *ce);
 
 struct cache_def {
 	struct strbuf path;
diff --git a/entry.c b/entry.c
index 0a3c451f5f..b9eef57117 100644
--- a/entry.c
+++ b/entry.c
@@ -508,3 +508,18 @@ int checkout_entry(struct cache_entry *ce,
 	create_directories(path.buf, path.len, state);
 	return write_entry(ce, path.buf, state, 0);
 }
+
+void unlink_entry(const struct cache_entry *ce)
+{
+	const struct submodule *sub = submodule_from_ce(ce);
+	if (sub) {
+		/* state.force is set at the caller. */
+		submodule_move_head(ce->name, "HEAD", NULL,
+				    SUBMODULE_MOVE_HEAD_FORCE);
+	}
+	if (!check_leading_path(ce->name, ce_namelen(ce)))
+		return;
+	if (remove_or_warn(ce->ce_mode, ce->name))
+		return;
+	schedule_dir_for_removal(ce->name, ce_namelen(ce));
+}
diff --git a/unpack-trees.c b/unpack-trees.c
index 7570df481b..e8d1a6ac50 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -300,25 +300,6 @@ static void load_gitmodules_file(struct index_state *index,
 	}
 }
 
-/*
- * Unlink the last component and schedule the leading directories for
- * removal, such that empty directories get removed.
- */
-static void unlink_entry(const struct cache_entry *ce)
-{
-	const struct submodule *sub = submodule_from_ce(ce);
-	if (sub) {
-		/* state.force is set at the caller. */
-		submodule_move_head(ce->name, "HEAD", NULL,
-				    SUBMODULE_MOVE_HEAD_FORCE);
-	}
-	if (!check_leading_path(ce->name, ce_namelen(ce)))
-		return;
-	if (remove_or_warn(ce->ce_mode, ce->name))
-		return;
-	schedule_dir_for_removal(ce->name, ce_namelen(ce));
-}
-
 static struct progress *get_progress(struct unpack_trees_options *o)
 {
 	unsigned cnt = 0, total = 0;
-- 
2.20.1.153.gd81d796ee0


^ permalink raw reply related

* [PATCH v3 0/8] introduce no-overlay mode in git checkout
From: Thomas Gummerer @ 2019-01-08 21:52 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Nguyễn Thái Ngọc Duy,
	Elijah Newren, Eric Sunshine, Thomas Gummerer
In-Reply-To: <20181220134820.21810-1-t.gummerer@gmail.com>

Previous rounds are at <20181209200449.16342-1-t.gummerer@gmail.com>
and <20181220134820.21810-1-t.gummerer@gmail.com>.

Thanks Duy, Eric and Junio for comments on the previous round.

This round fixes some inconsistencies and improves the grammar in the
docs.  Range-diff below:

1:  fa450cda7c = 1:  fa450cda7c move worktree tests to t24*
2:  9ada8d3484 = 2:  9ada8d3484 entry: factor out unlink_entry function
3:  41c0ea4047 = 3:  41c0ea4047 entry: support CE_WT_REMOVE flag in checkout_entry
4:  afccb0848d = 4:  afccb0848d read-cache: add invalidate parameter to remove_marked_cache_entries
5:  8a2b5efdad = 5:  8a2b5efdad checkout: clarify comment
6:  c405f20471 = 6:  c405f20471 checkout: factor out mark_cache_entry_for_checkout function
7:  e5b18bcd02 ! 7:  a291dc78fa checkout: introduce --{,no-}overlay option
    @@ -35,7 +35,7 @@
      section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
     ++
     +Note that this option uses the no overlay mode by default (see also
    -+-`--[no-]overlay`), and currently doesn't support overlay mode.
    ++`--[no-]overlay`), and currently doesn't support overlay mode.
      
      --ignore-other-worktrees::
      	`git checkout` refuses when the wanted ref is already checked
    @@ -44,9 +44,9 @@
      	submodules HEAD.
      
     +--[no-]overlay::
    -+	In the default overlay mode files `git checkout` never
    ++	In the default overlay mode, `git checkout` never
     +	removes files from the index or the working tree.  When
    -+	specifying --no-overlay, files that appear in the index and
    ++	specifying `--no-overlay`, files that appear in the index and
     +	working tree, but not in <tree-ish> are removed, to make them
     +	match <tree-ish> exactly.
     +
8:  de24990d57 ! 8:  8d4070f142 checkout: introduce checkout.overlayMode config
    @@ -19,9 +19,9 @@
      	settings nor will it show the local changes.
     +
     +checkout.overlayMode::
    -+	In the default overlay mode files `git checkout` never
    ++	In the default overlay mode, `git checkout` never
     +	removes files from the index or the working tree.  When
    -+	setting checkout.overlayMode to false, files that appear in
    ++	setting `checkout.overlayMode` to false, files that appear in
     +	the index and working tree, but not in <tree-ish> are removed,
     +	to make them match <tree-ish> exactly.

Thomas Gummerer (8):
  move worktree tests to t24*
  entry: factor out unlink_entry function
  entry: support CE_WT_REMOVE flag in checkout_entry
  read-cache: add invalidate parameter to remove_marked_cache_entries
  checkout: clarify comment
  checkout: factor out mark_cache_entry_for_checkout function
  checkout: introduce --{,no-}overlay option
  checkout: introduce checkout.overlayMode config

 Documentation/config/checkout.txt             |   7 +
 Documentation/git-checkout.txt                |  10 ++
 builtin/checkout.c                            | 133 +++++++++++++-----
 cache.h                                       |   7 +-
 entry.c                                       |  26 ++++
 read-cache.c                                  |   8 +-
 split-index.c                                 |   2 +-
 t/t2025-checkout-no-overlay.sh                |  57 ++++++++
 ...-worktree-add.sh => t2400-worktree-add.sh} |   0
 ...ktree-prune.sh => t2401-worktree-prune.sh} |   0
 ...orktree-list.sh => t2402-worktree-list.sh} |   0
 ...orktree-move.sh => t2403-worktree-move.sh} |   0
 ...ree-config.sh => t2404-worktree-config.sh} |   0
 t/t9902-completion.sh                         |   1 +
 unpack-trees.c                                |  21 +--
 15 files changed, 213 insertions(+), 59 deletions(-)
 create mode 100755 t/t2025-checkout-no-overlay.sh
 rename t/{t2025-worktree-add.sh => t2400-worktree-add.sh} (100%)
 rename t/{t2026-worktree-prune.sh => t2401-worktree-prune.sh} (100%)
 rename t/{t2027-worktree-list.sh => t2402-worktree-list.sh} (100%)
 rename t/{t2028-worktree-move.sh => t2403-worktree-move.sh} (100%)
 rename t/{t2029-worktree-config.sh => t2404-worktree-config.sh} (100%)

-- 
2.20.1.153.gd81d796ee0

     

^ permalink raw reply

* Re: sb/more-repo-in-api, was Re: What's cooking in git.git (Jan 2019, #01; Mon, 7)
From: Junio C Hamano @ 2019-01-08 21:35 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: git, stolee
In-Reply-To: <20190108212007.10855-1-jonathantanmy@google.com>

Jonathan Tan <jonathantanmy@google.com> writes:

>>  The in-core repository instances are passed through more codepaths.
>
> I think this is ready to be considered for merging to next. This series looks
> good both to Stolee [1] and to me (I replied to a previous version with
> comments on patch 18 [2] which Stefan has addressed, as can be seen in the
> inter-diff provided by Junio [3] - I probably should have replied to the latest
> version stating this too).

Alright, thanks.

While attempting to resolve conflicts with this and Peff's "get rid
of has_sha1_file()" topic, I found it somewhat disturbing that
sha1-file.c still was a mixture of functions that do and do not take
the repository pointer, but perhaps it's something we need to polish
over time on top.

^ permalink raw reply

* Re: [PATCH 3/3] t0006-date.sh: add `human` date format tests.
From: Johannes Sixt @ 2019-01-08 21:27 UTC (permalink / raw)
  To: Stephen P . Smith
  Cc: git, Linus Torvalds, Junio C Hamano,
	Ævar Arnfjörð Bjarmason
In-Reply-To: <20181231003150.8031-4-ischis2@cox.net>

Am 31.12.18 um 01:31 schrieb Stephen P. Smith:
> +check_human_date () {
> +	time=$1
> +	expect=$2
> +	test_expect_success "check date ($format:$time)" '
> +		echo "$time -> $expect" >expect &&
> +		TZ=${zone:-$TZ} test-tool date show:"$format" "$time" >actual &&
> +		grep "$expect" actual
> +	'
> +}
> +
>   # arbitrary but sensible time for examples
>   TIME='1466000000 +0200'
>   check_show iso8601 "$TIME" '2016-06-15 16:13:20 +0200'
> @@ -52,6 +62,20 @@ check_show unix "$TIME" '1466000000'
>   check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000'
>   check_show raw-local "$TIME" '1466000000 +0000'
>   check_show unix-local "$TIME" '1466000000'
> +check_show human "$TIME" 'Jun 15 2016'
> +
> +# Subtract some known constant time and look for expected field format
> +TODAY_REGEX='5 hours ago'
> +THIS_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [012][0-9]:[0-6][0-9]'
> +MORE_THAN_A_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [0-9][0-9][0-9][0-9]'
> +check_human_date "$(($(date +%s)-18000)) +0200" $TODAY_REGEX # 5 hours ago
> +check_human_date "$(($(date +%s)-432000)) +0200" $THIS_YEAR_REGEX  # 5 days ago
> +check_human_date "$(($(date +%s)-1728000)) +0200" $THIS_YEAR_REGEX # 3 weeks ago
> +check_human_date "$(($(date +%s)-13000000)) +0200" $THIS_YEAR_REGEX # 5 months ago
> +check_human_date "$(($(date +%s)-31449600)) +0200" $THIS_YEAR_REGEX # 12 months ago
> +check_human_date "$(($(date +%s)-37500000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 2 months ago
> +check_human_date "$(($(date +%s)-55188000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 9 months ago
> +check_human_date "$(($(date +%s)-630000000)) +0200" $MORE_THAN_A_YEAR_REGEX # 20 years ago
>   
>   check_show 'format:%z' "$TIME" '+0200'
>   check_show 'format-local:%z' "$TIME" '+0000'
> diff --git a/t/t4202-log.sh b/t/t4202-log.sh
> index 819c24d10e..d7f3b73650 100755
> --- a/t/t4202-log.sh
> +++ b/t/t4202-log.sh
> @@ -1707,4 +1707,28 @@ test_expect_success '--exclude-promisor-objects does not BUG-crash' '
>   	test_must_fail git log --exclude-promisor-objects source-a
>   '
>   
> +check_human_date() {
> +	commit_date=$1
> +	expect=$2
> +	test_expect_success "$commit_date" "
> +		echo $expect $commit_date >dates &&
> +		git add dates &&
> +		git commit -m 'Expect String' --date=\"$commit_date\" dates &&
> +		git log -1 --date=human | grep \"^Date:\" >actual &&
> +		grep \"$expect\" actual
> +"
> +}
> +
> +TODAY_REGEX='[A-Z][a-z][a-z] [012][0-9]:[0-6][0-9] .0200'
> +THIS_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [012][0-9]:[0-6][0-9]'
> +MORE_THAN_A_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [0-9][0-9][0-9][0-9]'
> +check_human_date "$(($(date +%s)-18000)) +0200" $TODAY_REGEX # 5 hours ago
> +check_human_date "$(($(date +%s)-432000)) +0200" $THIS_YEAR_REGEX  # 5 days ago
> +check_human_date "$(($(date +%s)-1728000)) +0200" $THIS_YEAR_REGEX # 3 weeks ago
> +check_human_date "$(($(date +%s)-13000000)) +0200" $THIS_YEAR_REGEX # 5 months ago
> +check_human_date "$(($(date +%s)-31449600)) +0200" $THIS_YEAR_REGEX # 12 months ago
> +check_human_date "$(($(date +%s)-37500000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 2 months ago
> +check_human_date "$(($(date +%s)-55188000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 9 months ago
> +check_human_date "$(($(date +%s)-630000000)) +0200" $MORE_THAN_A_YEAR_REGEX # 20 years ago
> +
>   test_done
> diff --git a/t/t7007-show.sh b/t/t7007-show.sh
> index 42d3db6246..0a0334a8b5 100755
> --- a/t/t7007-show.sh
> +++ b/t/t7007-show.sh
> @@ -128,4 +128,29 @@ test_expect_success 'show --graph is forbidden' '
>     test_must_fail git show --graph HEAD
>   '
>   
> +check_human_date() {
> +	commit_date=$1
> +	expect=$2
> +	test_expect_success "$commit_date" "
> +		echo $expect $commit_date >dates &&
> +		git add dates &&
> +		git commit -m 'Expect String' --date=\"$commit_date\" dates &&
> +		git show --date=human | grep \"^Date:\" >actual &&
> +		grep \"$expect\" actual
> +"
> +}
> +
> +TODAY_REGEX='[A-Z][a-z][a-z] [012][0-9]:[0-6][0-9] .0200'
> +THIS_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [012][0-9]:[0-6][0-9]'
> +MORE_THAN_A_YEAR_REGEX='[A-Z][a-z][a-z] [A-Z][a-z][a-z] [0-9]* [0-9][0-9][0-9][0-9]'
> +check_human_date "$(($(date +%s)-18000)) +0200" $TODAY_REGEX # 5 hours ago
> +check_human_date "$(($(date +%s)-432000)) +0200" $THIS_YEAR_REGEX  # 5 days ago
> +check_human_date "$(($(date +%s)-1728000)) +0200" $THIS_YEAR_REGEX # 3 weeks ago
> +check_human_date "$(($(date +%s)-13000000)) +0200" $THIS_YEAR_REGEX # 5 months ago
> +check_human_date "$(($(date +%s)-31449600)) +0200" $THIS_YEAR_REGEX # 12 months ago
> +check_human_date "$(($(date +%s)-37500000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 2 months ago
> +check_human_date "$(($(date +%s)-55188000)) +0200" $MORE_THAN_A_YEAR_REGEX # 1 year, 9 months ago
> +check_human_date "$(($(date +%s)-630000000)) +0200" $MORE_THAN_A_YEAR_REGEX # 20 years ago

The $...REGEX expansions must be put in double-quotes to protect them 
from field splitting. But then the tests do not pass anymore (I tested 
only t4202). Please revisit this change.

-- Hannes

^ permalink raw reply

* Re: git rebase: retain original head?
From: Jacob Keller @ 2019-01-08 21:22 UTC (permalink / raw)
  To: Markus Wiederkehr; +Cc: Git mailing list
In-Reply-To: <CA+h-BnvN7+ETU-vFxAGDvs0gvXUjAAhMkvTPUxoRTt2Gb4b2ow@mail.gmail.com>

On Tue, Jan 8, 2019 at 12:47 PM Markus Wiederkehr
<markus.wiederkehr@gmail.com> wrote:
>
> On Tue, Jan 8, 2019 at 6:43 PM Andreas Schwab <schwab@linux-m68k.org> wrote:
> >
> > On Jan 08 2019, Markus Wiederkehr <markus.wiederkehr@gmail.com> wrote:
> >
> > > Would it be possible to retain this information?
> >
> > You could use the reflog of the current branch, where it is the second
> > entry.
>
> It is not, depending on what happens in the rebase it could be any
> entry. That's why I always have to search for the right one, which is
> tedious.
>
> Example:
>
> $ git rebase -i root-tag
> ... (apply one fixup)
> $ git reflog
> 906caf1c (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to
> refs/heads/master
> 4906caf1c (HEAD -> master) HEAD@{1}: rebase -i (pick): qux
> 85dab37b4 HEAD@{2}: rebase -i (pick): baz
> 7de7420d2 HEAD@{3}: rebase -i (fixup): bar
> 9bc0461c0 HEAD@{4}: rebase -i (start): checkout root-tag
> a150b73ca HEAD@{5}: commit: foo
>
> Here I have to use HEAD@{5}.
>

He meant using:

$ git reflog master

which only shows changes directly to the master ref, not to HEAD.
During a git rebase operations don't modify the master ref until after
the rebase finishes. This, of course, assumes you're on a branch.

If so, you should even be able to use master@{1} and be safe in
assuming it always refers to what the branch was before the rebase
started.

Thanks,
Jake

^ permalink raw reply

* sb/more-repo-in-api, was Re: What's cooking in git.git (Jan 2019, #01; Mon, 7)
From: Jonathan Tan @ 2019-01-08 21:20 UTC (permalink / raw)
  To: gitster; +Cc: git, stolee, Jonathan Tan
In-Reply-To: <xmqq7efg6o0d.fsf@gitster-ct.c.googlers.com>

> * sb/more-repo-in-api (2018-12-28) 23 commits
>  - t/helper/test-repository: celebrate independence from the_repository
>  - path.h: make REPO_GIT_PATH_FUNC repository agnostic
>  - commit: prepare free_commit_buffer and release_commit_memory for any repo
>  - commit-graph: convert remaining functions to handle any repo
>  - submodule: don't add submodule as odb for push
>  - submodule: use submodule repos for object lookup
>  - pretty: prepare format_commit_message to handle arbitrary repositories
>  - commit: prepare logmsg_reencode to handle arbitrary repositories
>  - commit: prepare repo_unuse_commit_buffer to handle any repo
>  - commit: prepare get_commit_buffer to handle any repo
>  - commit-reach: prepare in_merge_bases[_many] to handle any repo
>  - commit-reach: prepare get_merge_bases to handle any repo
>  - commit-reach.c: allow get_merge_bases_many_0 to handle any repo
>  - commit-reach.c: allow remove_redundant to handle any repo
>  - commit-reach.c: allow merge_bases_many to handle any repo
>  - commit-reach.c: allow paint_down_to_common to handle any repo
>  - commit: allow parse_commit* to handle any repo
>  - object: parse_object to honor its repository argument
>  - object-store: prepare has_{sha1, object}_file to handle any repo
>  - object-store: prepare read_object_file to deal with any repo
>  - object-store: allow read_object_file_extended to read from any repo
>  - packfile: allow has_packed_and_bad to handle arbitrary repositories
>  - sha1_file: allow read_object to read objects in arbitrary repositories
>  (this branch is used by jt/get-reference-with-commit-graph and md/list-objects-filter-by-depth.)
> 
>  The in-core repository instances are passed through more codepaths.

I think this is ready to be considered for merging to next. This series looks
good both to Stolee [1] and to me (I replied to a previous version with
comments on patch 18 [2] which Stefan has addressed, as can be seen in the
inter-diff provided by Junio [3] - I probably should have replied to the latest
version stating this too).

[1] https://public-inbox.org/git/b2ff842d-4d60-0db7-c11d-dcc006dade18@gmail.com/
[2] https://public-inbox.org/git/20181115221254.45373-1-jonathantanmy@google.com/
[3] https://public-inbox.org/git/xmqq36qho1gf.fsf@gitster-ct.c.googlers.com/

^ permalink raw reply

* Re: [PATCH 0/11] jk/loose-object-cache sha1/object_id fixups
From: Jeff King @ 2019-01-08 21:16 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: René Scharfe, git, Ævar Arnfjörð Bjarmason
In-Reply-To: <xmqq8szv56e4.fsf@gitster-ct.c.googlers.com>

On Tue, Jan 08, 2019 at 10:52:19AM -0800, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
> 
> > Jeff King <peff@peff.net> writes:
> >
> >> Yeah, they should. I think one of them will need René's patch, which
> >> changes the body of quick_has_loose(). I can roll it as a separate topic
> >> if that's easier (or just wait a week or so until René's cleanups
> >> graduate).
> >
> > Nah, what I got is already good to work with.  Both series are
> > straight-forward and I do not expect them needing long fermentation.
> 
> Yikes, the conflicts with sb/more-repo-in-api is quite irritating.
> I think I'll postpone the later parts of this series and ask this to
> be sent after sb/more-repo-in-api matures a bit mroe.

There were several conflicts, but it was mostly just tedious textual
fixups. I pushed the result to:

  https://github.com/peff/git.git resolve-oid-more-repo

But I'm happy to wait and rebase if sb/more-repo-in-api is close to
graduating.

-Peff

^ permalink raw reply

* Re: [PATCH v3 4/4] fetch-pack: support protocol version 2
From: Jeff King @ 2019-01-08 21:14 UTC (permalink / raw)
  To: Jonathan Tan; +Cc: gitster, avarab, git, bwilliamseng, steadmon
In-Reply-To: <20190108203826.564-1-jonathantanmy@google.com>

On Tue, Jan 08, 2019 at 12:38:26PM -0800, Jonathan Tan wrote:

> > Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
> > 
> > > From: Jonathan Tan <jonathantanmy@google.com>
> > 
> > 
> > I was looking at the topics in 'pu' and noticed that I had v2 of
> > this series, wanted to update to v3, but major part of it was
> > superseded by another topic (jk/proto-v2-hidden-refs-fix).  That
> > leaves only this patch in the v3 of this series.
> > 
> > Is this one still relevant?
> 
> This patch is more relevant to the GIT_TEST_PROTOCOL_VERSION patches,
> since it means that several tests work even if
> GIT_TEST_PROTOCOL_VERSION=2 is set. I think it can be dropped until
> someone restarts the GIT_TEST_PROTOCOL_VERSION effort, but I'm not sure
> if Ævar has another opinion.

I think it's independently useful. If you set protocol.version=2 in your
config, then you can no longer run fetch-pack directly. Most people
don't, but it's possible their scripts might (we also use fetch-pack
under the hood for smart-http, but I wasn't able to get it to complain,
though).

-Peff

^ permalink raw reply

* Re: git rebase: retain original head?
From: Andreas Schwab @ 2019-01-08 20:51 UTC (permalink / raw)
  To: Markus Wiederkehr; +Cc: git
In-Reply-To: <CA+h-BnvN7+ETU-vFxAGDvs0gvXUjAAhMkvTPUxoRTt2Gb4b2ow@mail.gmail.com>

On Jan 08 2019, Markus Wiederkehr <markus.wiederkehr@gmail.com> wrote:

> On Tue, Jan 8, 2019 at 6:43 PM Andreas Schwab <schwab@linux-m68k.org> wrote:
>>
>> On Jan 08 2019, Markus Wiederkehr <markus.wiederkehr@gmail.com> wrote:
>>
>> > Would it be possible to retain this information?
>>
>> You could use the reflog of the current branch, where it is the second
>> entry.
>
> It is not, depending on what happens in the rebase it could be any
> entry.

Don't look at the HEAD reflog, use the branch reflog, ie. @{1}.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply

* Re: git rebase: retain original head?
From: Markus Wiederkehr @ 2019-01-08 20:38 UTC (permalink / raw)
  To: git
In-Reply-To: <87va2zavu1.fsf@igel.home>

On Tue, Jan 8, 2019 at 6:43 PM Andreas Schwab <schwab@linux-m68k.org> wrote:
>
> On Jan 08 2019, Markus Wiederkehr <markus.wiederkehr@gmail.com> wrote:
>
> > Would it be possible to retain this information?
>
> You could use the reflog of the current branch, where it is the second
> entry.

It is not, depending on what happens in the rebase it could be any
entry. That's why I always have to search for the right one, which is
tedious.

Example:

$ git rebase -i root-tag
... (apply one fixup)
$ git reflog
906caf1c (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to
refs/heads/master
4906caf1c (HEAD -> master) HEAD@{1}: rebase -i (pick): qux
85dab37b4 HEAD@{2}: rebase -i (pick): baz
7de7420d2 HEAD@{3}: rebase -i (fixup): bar
9bc0461c0 HEAD@{4}: rebase -i (start): checkout root-tag
a150b73ca HEAD@{5}: commit: foo

Here I have to use HEAD@{5}.

Markus

On Tue, Jan 8, 2019 at 6:43 PM Andreas Schwab <schwab@linux-m68k.org> wrote:
>
> On Jan 08 2019, Markus Wiederkehr <markus.wiederkehr@gmail.com> wrote:
>
> > During the rebase operation the original head seems to get stored in
> > 'rebase-merge/orig-head'. Unfortunately this references gets removed
> > after the rebase operation completes.
> >
> > Would it be possible to retain this information?
>
> You could use the reflog of the current branch, where it is the second
> entry.
>
> Andreas.
>
> --
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
> "And now for something completely different."

^ permalink raw reply

* Re: [PATCH v3 4/4] fetch-pack: support protocol version 2
From: Jonathan Tan @ 2019-01-08 20:38 UTC (permalink / raw)
  To: gitster; +Cc: avarab, git, peff, bwilliamseng, jonathantanmy, steadmon
In-Reply-To: <xmqqva2z3pdp.fsf@gitster-ct.c.googlers.com>

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
> 
> > From: Jonathan Tan <jonathantanmy@google.com>
> 
> 
> I was looking at the topics in 'pu' and noticed that I had v2 of
> this series, wanted to update to v3, but major part of it was
> superseded by another topic (jk/proto-v2-hidden-refs-fix).  That
> leaves only this patch in the v3 of this series.
> 
> Is this one still relevant?

This patch is more relevant to the GIT_TEST_PROTOCOL_VERSION patches,
since it means that several tests work even if
GIT_TEST_PROTOCOL_VERSION=2 is set. I think it can be dropped until
someone restarts the GIT_TEST_PROTOCOL_VERSION effort, but I'm not sure
if Ævar has another opinion.

^ permalink raw reply

* Re: [PATCH v4 0/1] pack-redundant: remove unused functions
From: Junio C Hamano @ 2019-01-08 19:30 UTC (permalink / raw)
  To: 16657101987; +Cc: worldhello.net, git, sunchao9
In-Reply-To: <20190108164100.73219-1-16657101987@163.com>

16657101987@163.com writes:

> From: Sun Chao <sunchao9@huawei.com>
>
> I'm particularly grateful to Junio and JiangXin for fixing the patches,
> and I noticed Junio send a new commit to remove more unused codes and
> suggest to SQUASH it.
>
> So I create this new version of patches to do this work, I also have
> checked the left codes and remove a unused struct based on Junio's
> last commit of `https://github.com/gitster/git/commits/sc/pack-redundant`.
>
> --
>
> Sun Chao (1):
>   pack-redundant: remove unused functions

Is this meant to replace [v3 3/3]?


^ permalink raw reply

* Re: [PATCH v3 4/4] fetch-pack: support protocol version 2
From: Junio C Hamano @ 2019-01-08 19:45 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, Brandon Williams, Jonathan Tan, Josh Steadmon
In-Reply-To: <20181217224054.4376-5-avarab@gmail.com>

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> From: Jonathan Tan <jonathantanmy@google.com>


I was looking at the topics in 'pu' and noticed that I had v2 of
this series, wanted to update to v3, but major part of it was
superseded by another topic (jk/proto-v2-hidden-refs-fix).  That
leaves only this patch in the v3 of this series.

Is this one still relevant?

> diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
> index 086f2c40f68..49c540b1e1d 100755
> --- a/t/t5500-fetch-pack.sh
> +++ b/t/t5500-fetch-pack.sh
> @@ -439,15 +439,23 @@ test_expect_success 'setup tests for the --stdin parameter' '
>  	) >input.dup
>  '
>  
> -test_expect_success 'fetch refs from cmdline' '
> -	(
> -		cd client &&
> -		git fetch-pack --no-progress .. $(cat ../input)
> -	) >output &&
> -	cut -d " " -f 2 <output | sort >actual &&
> -	test_cmp expect actual
> +test_expect_success 'setup fetch refs from cmdline v[12]' '
> +	cp -r client client1 &&
> +	cp -r client client2
>  '
>  
> +for version in '' 1 2
> +do
> +	test_expect_success "protocol.version=$version fetch refs from cmdline" "
> +		(
> +			cd client$version &&
> +			GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. \$(cat ../input)
> +		) >output &&
> +		cut -d ' ' -f 2 <output | sort >actual &&
> +		test_cmp expect actual
> +	"
> +done
> +
>  test_expect_success 'fetch refs from stdin' '
>  	(
>  		cd client &&

^ permalink raw reply

* RE: error: Use of uninitialized value $hash in chomp
From: Andrew Shearer @ 2019-01-08 19:44 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git@vger.kernel.org, Eric Wong
In-Reply-To: <ME1PR01MB11218D4953017CFE06A2B16AE1B80@ME1PR01MB1121.ausprd01.prod.outlook.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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox