Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-12-03 Thread Junio C Hamano
Jeff King  writes:

> That said, our C99 designated initializer weather-balloons haven't
> gotten any complaints yet. So I think you could actually do:
>
>   struct setup_revision_opt s_r_opt = {
>   .allow_exclude_promisor_objects = 1,
>   };
>   ...
>   setup_revisions(...);
>
> which is pretty nice.

Yup.  The output from 

$ git grep -n ' \.[a-z0-9_]* =' -- \*.[ch]

with a bit of "git blame" tells us that cbc0f81d ("strbuf: use
designated initializers in STRBUF_INIT", 2017-07-10) is the balloon
for this exact feature.  The same for array was done in 512f41cf
("clean.c: use designated initializer", 2017-07-14)

[I am writing it down so that I do not have to dig for it every time
and instead can ask the list archive]




Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-12-03 Thread Matthew DeVore

On 12/03/2018 01:15 PM, Jeff King wrote:

That said, our C99 designated initializer weather-balloons haven't
gotten any complaints yet. So I think you could actually do:

   struct setup_revision_opt s_r_opt = {
.allow_exclude_promisor_objects = 1,
   };


I like this way best, so I'll use it. Thank you.


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-12-03 Thread Jeff King
On Mon, Dec 03, 2018 at 11:10:49AM -0800, Matthew DeVore wrote:

> > > + memset(_r_opt, 0, sizeof(s_r_opt));
> > > + s_r_opt.allow_exclude_promisor_objects = 1;
> > > + setup_revisions(ac, av, , _r_opt);
> > 
> > I wonder if a static initializer for setup_revision_opt is worth it. It
> > would remove the need for this memset. Probably not a big deal either
> > way, though.
> I think you mean something like this:
> 
> static struct setup_revision_opt s_r_opt = {NULL, NULL, NULL, 0, 1, 0};
> 
> This is a bit cryptic (I have to read the struct declaration in order to
> know what is being set to 1) and if the struct ever gets a new field before
> allow_exclude_promisor_objects, this initializer has to be updated.

I agree that's pretty awful.  I meant something like this:

  struct setup_revision_opt s_r_opt = { NULL };
  ...

  s_r_opt.allow_exclude_promisor_objects = 1;
  setup_revisions(...);

It's functionally equivalent to the memset(), but you don't have to
wonder about whether we peek at the uninitialized state in between.

That said, our C99 designated initializer weather-balloons haven't
gotten any complaints yet. So I think you could actually do:

  struct setup_revision_opt s_r_opt = {
.allow_exclude_promisor_objects = 1,
  };
  ...
  setup_revisions(...);

which is pretty nice.

-Peff


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-12-03 Thread Matthew DeVore

On 12/01/2018 11:44 AM, Jeff King wrote:

repo_init_revisions(the_repository, , NULL);
save_commit_buffer = 0;
-   revs.allow_exclude_promisor_objects_opt = 1;
-   setup_revisions(ac, av, , NULL);
+
+   memset(_r_opt, 0, sizeof(s_r_opt));
+   s_r_opt.allow_exclude_promisor_objects = 1;
+   setup_revisions(ac, av, , _r_opt);


I wonder if a static initializer for setup_revision_opt is worth it. It
would remove the need for this memset. Probably not a big deal either
way, though.

I think you mean something like this:

static struct setup_revision_opt s_r_opt = {NULL, NULL, NULL, 0, 1, 0};

This is a bit cryptic (I have to read the struct declaration in order to 
know what is being set to 1) and if the struct ever gets a new field 
before allow_exclude_promisor_objects, this initializer has to be updated.





  static int handle_revision_opt(struct rev_info *revs, int argc, const char
**argv,
-  int *unkc, const char **unkv)
+  int *unkc, const char **unkv,
+  int allow_exclude_promisor_objects)


Why not pass in the whole setup_revision_opt struct? We don't need
anything else from it yet, but it seems like the point of that struct is
to pass around preferences like this.

OK, the code reads better if I do that, so I agree.



-Peff



Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-12-01 Thread Jeff King
On Fri, Nov 30, 2018 at 05:32:47PM -0800, Matthew DeVore wrote:

> > Speaking of which, would this flag work better as a field in
> > setup_revision_opt, which is passed to setup_revisions()? The intent
> > seem to be to influence how we parse command-line arguments, and that's
> > where other similar flags are (e.g., assume_dashdash).
> 
> Good idea. This would solve the problem of mistakenly believing the flag
> matters when it doesn't, since it is in the struct which is used as the
> arguments of the exact function that cares about it. Here's a new patch -
> I'm tweaking e-mail client settings so hopefully this makes it to the list
> without mangling - if not I'll resend it with `git-send-email` later.
> 
> From 941c89fe1e226ed4d210ce35d0d906526b8277ed Mon Sep 17 00:00:00 2001
> From: Matthew DeVore 
> Date: Fri, 30 Nov 2018 16:43:32 -0800
> Subject: [PATCH] revisions.c: put promisor option in specialized struct
> 
> Put the allow_exclude_promisor_objects flag in setup_revision_opt. When
> it was in rev_info, it was unclear when it was used, since rev_info is
> passed to functions that don't use the flag. This resulted in
> unnecessary setting of the flag in prune.c, so fix that as well.

Thanks, this looks pretty reasonable overall. Two comments:

>   repo_init_revisions(the_repository, , NULL);
>   save_commit_buffer = 0;
> - revs.allow_exclude_promisor_objects_opt = 1;
> - setup_revisions(ac, av, , NULL);
> +
> + memset(_r_opt, 0, sizeof(s_r_opt));
> + s_r_opt.allow_exclude_promisor_objects = 1;
> + setup_revisions(ac, av, , _r_opt);

I wonder if a static initializer for setup_revision_opt is worth it. It
would remove the need for this memset. Probably not a big deal either
way, though.

>  static int handle_revision_opt(struct rev_info *revs, int argc, const char
> **argv,
> -int *unkc, const char **unkv)
> +int *unkc, const char **unkv,
> +int allow_exclude_promisor_objects)

Why not pass in the whole setup_revision_opt struct? We don't need
anything else from it yet, but it seems like the point of that struct is
to pass around preferences like this.

-Peff


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-11-30 Thread Matthew DeVore




On 11/21/2018 08:40 AM, Jeff King wrote:

On Mon, Oct 22, 2018 at 06:13:42PM -0700, Matthew DeVore wrote:


diff --git a/builtin/prune.c b/builtin/prune.c
index 41230f8215..11284d0bf3 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -120,6 +120,7 @@ int cmd_prune(int argc, const char **argv, const char 
*prefix)
save_commit_buffer = 0;
read_replace_refs = 0;
ref_paranoia = 1;
+   revs.allow_exclude_promisor_objects_opt = 1;
repo_init_revisions(the_repository, , prefix);
  
  	argc = parse_options(argc, argv, prefix, options, prune_usage, 0);


I think this line is in the wrong place. The very first thing
repo_init_revisions() will do is memset() the revs struct to all-zeroes,
so it cannot possibly be doing anything.


Ah of course :)



Normally it would need to go after init_revisions() but before
setup_revisions(), but we don't seem to call the latter at all in
builtin/prune.c. Which makes sense, because you cannot pass options to
influence the reachability traversal. So I don't think we need to care
about this flag at all here.
Agreed, prune.c doesn't use setup_revisions() even transitively, so we 
don't care about this flag.




Speaking of which, would this flag work better as a field in
setup_revision_opt, which is passed to setup_revisions()? The intent
seem to be to influence how we parse command-line arguments, and that's
where other similar flags are (e.g., assume_dashdash).


Good idea. This would solve the problem of mistakenly believing the flag 
matters when it doesn't, since it is in the struct which is used as the 
arguments of the exact function that cares about it. Here's a new patch 
- I'm tweaking e-mail client settings so hopefully this makes it to the 
list without mangling - if not I'll resend it with `git-send-email` later.


From 941c89fe1e226ed4d210ce35d0d906526b8277ed Mon Sep 17 00:00:00 2001
From: Matthew DeVore 
Date: Fri, 30 Nov 2018 16:43:32 -0800
Subject: [PATCH] revisions.c: put promisor option in specialized struct

Put the allow_exclude_promisor_objects flag in setup_revision_opt. When
it was in rev_info, it was unclear when it was used, since rev_info is
passed to functions that don't use the flag. This resulted in
unnecessary setting of the flag in prune.c, so fix that as well.

Signed-off-by: Matthew DeVore 
---
 builtin/pack-objects.c |  7 +--
 builtin/prune.c|  1 -
 builtin/rev-list.c |  6 --
 revision.c | 17 -
 revision.h |  4 ++--
 5 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 24bba8147f..b22c99f540 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3084,14 +3084,17 @@ static void record_recent_commit(struct commit 
*commit, void *data)

 static void get_object_list(int ac, const char **av)
 {
struct rev_info revs;
+   struct setup_revision_opt s_r_opt;
char line[1000];
int flags = 0;
int save_warning;

repo_init_revisions(the_repository, , NULL);
save_commit_buffer = 0;
-   revs.allow_exclude_promisor_objects_opt = 1;
-   setup_revisions(ac, av, , NULL);
+
+   memset(_r_opt, 0, sizeof(s_r_opt));
+   s_r_opt.allow_exclude_promisor_objects = 1;
+   setup_revisions(ac, av, , _r_opt);

/* make sure shallows are read */
is_repository_shallow(the_repository);
diff --git a/builtin/prune.c b/builtin/prune.c
index e42653b99c..1ec9ddd751 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -120,7 +120,6 @@ int cmd_prune(int argc, const char **argv, const 
char *prefix)

save_commit_buffer = 0;
read_replace_refs = 0;
ref_paranoia = 1;
-   revs.allow_exclude_promisor_objects_opt = 1;
repo_init_revisions(the_repository, , prefix);

argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 3a2c0c23b6..c3095c6fed 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -362,6 +362,7 @@ int cmd_rev_list(int argc, const char **argv, const 
char *prefix)

 {
struct rev_info revs;
struct rev_list_info info;
+   struct setup_revision_opt s_r_opt;
int i;
int bisect_list = 0;
int bisect_show_vars = 0;
@@ -375,7 +376,6 @@ int cmd_rev_list(int argc, const char **argv, const 
char *prefix)

git_config(git_default_config, NULL);
repo_init_revisions(the_repository, , prefix);
revs.abbrev = DEFAULT_ABBREV;
-   revs.allow_exclude_promisor_objects_opt = 1;
revs.commit_format = CMIT_FMT_UNSPECIFIED;
revs.do_not_die_on_missing_tree = 1;

@@ -407,7 +407,9 @@ int cmd_rev_list(int argc, const char **argv, const 
char *prefix)

}
}

-   argc = setup_revisions(argc, argv, , NULL);
+   memset(_r_opt, 0, sizeof(s_r_opt));
+   s_r_opt.allow_exclude_promisor_objects = 1;
+   argc = 

Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-11-21 Thread Jeff King
On Mon, Oct 22, 2018 at 06:13:42PM -0700, Matthew DeVore wrote:

> diff --git a/builtin/prune.c b/builtin/prune.c
> index 41230f8215..11284d0bf3 100644
> --- a/builtin/prune.c
> +++ b/builtin/prune.c
> @@ -120,6 +120,7 @@ int cmd_prune(int argc, const char **argv, const char 
> *prefix)
>   save_commit_buffer = 0;
>   read_replace_refs = 0;
>   ref_paranoia = 1;
> + revs.allow_exclude_promisor_objects_opt = 1;
>   repo_init_revisions(the_repository, , prefix);
>  
>   argc = parse_options(argc, argv, prefix, options, prune_usage, 0);

I think this line is in the wrong place. The very first thing
repo_init_revisions() will do is memset() the revs struct to all-zeroes,
so it cannot possibly be doing anything.

Normally it would need to go after init_revisions() but before
setup_revisions(), but we don't seem to call the latter at all in
builtin/prune.c. Which makes sense, because you cannot pass options to
influence the reachability traversal. So I don't think we need to care
about this flag at all here.

Speaking of which, would this flag work better as a field in
setup_revision_opt, which is passed to setup_revisions()? The intent
seem to be to influence how we parse command-line arguments, and that's
where other similar flags are (e.g., assume_dashdash).

-Peff


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-10-23 Thread Junio C Hamano
Matthew DeVore  writes:

> On Tue, 23 Oct 2018, Junio C Hamano wrote:
>
>> Not really.  We were already doing a controlled failure via die(),
>> so these two tests would not have caught the problem in the code
>> before the fix in this patch.
>>
>
> BUG is apparently considered a "wrong" failure and not a controlled one
> by test_must_fail. I just double-checked that the tests fail without
> this patch.

Ah, I was testing a wrong codepath.  Yes, it does call BUG("..."),
which is a prettier-looking abort(), but I somehow thought it was
doing die("BUG: ...").

In any case, thanks for the fix.


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-10-23 Thread Matthew DeVore




On Tue, 23 Oct 2018, Junio C Hamano wrote:


Not really.  We were already doing a controlled failure via die(),
so these two tests would not have caught the problem in the code
before the fix in this patch.



BUG is apparently considered a "wrong" failure and not a controlled one
by test_must_fail. I just double-checked that the tests fail without
this patch.

not ok 119 - --exclude-promisor-objects does not BUG-crash
# 
#		test_must_fail git blame --exclude-promisor-objects one
# 
# failed 1 among 119 test(s)

1..119


Re: [RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-10-22 Thread Junio C Hamano
Matthew DeVore  writes:

>  t/t4202-log.sh | 4 
>  t/t8002-blame.sh   | 4 
>  7 files changed, 14 insertions(+), 1 deletion(-)
> ...
> diff --git a/t/t4202-log.sh b/t/t4202-log.sh
> index 153a506151..819c24d10e 100755
> --- a/t/t4202-log.sh
> +++ b/t/t4202-log.sh
> @@ -1703,4 +1703,8 @@ test_expect_success 'log --source paints symmetric 
> ranges' '
>   test_cmp expect actual
>  '
>  
> +test_expect_success '--exclude-promisor-objects does not BUG-crash' '
> + test_must_fail git log --exclude-promisor-objects source-a
> +'
> +
>  test_done
> diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
> index 380e1c1054..eea048e52c 100755
> --- a/t/t8002-blame.sh
> +++ b/t/t8002-blame.sh
> @@ -118,4 +118,8 @@ test_expect_success '--no-abbrev works like --abbrev=40' '
>   check_abbrev 40 --no-abbrev
>  '
>  
> +test_expect_success '--exclude-promisor-objects does not BUG-crash' '
> + test_must_fail git blame --exclude-promisor-objects one
> +'
> +
>  test_done

OK.  We used to be hitting BUG() which is an abort() in disguise, so
must-fail would have caught it without the fix in this patch.  Now
we would see a more controlled failure.

... goes and makes sure that is the case ...

Not really.  We were already doing a controlled failure via die(),
so these two tests would not have caught the problem in the code
before the fix in this patch.

But nevertheless this is a good change; I do not think it is worth
grepping for "unrecognized option" to differentiate the two cases.

Thanks.


[RFC 2/2] exclude-promisor-objects: declare when option is allowed

2018-10-22 Thread Matthew DeVore
The --exclude-promisor-objects option causes some funny behavior in at
least two commands: log and blame. It causes a BUG crash:

$ git log --exclude-promisor-objects
BUG: revision.c:2143: exclude_promisor_objects can only be used
when fetch_if_missing is 0
Aborted
[134]

Fix this such that the option is treated like any other unknown option.
The commands that must support it are limited, so declare in those
commands that the flag is supported. In particular:

pack-objects
prune
rev-list

The commands were found by searching for logic which parses
--exclude-promisor-objects outside of revision.c. Extra logic outside of
revision.c is needed because fetch_if_missing must be turned on before
revision.c sees the option or it will BUG-crash. The above list is
supported by the fact that no other command is introspectively invoked
by another command passing --exclude-promisor-object.

Signed-off-by: Matthew DeVore 
---
 builtin/pack-objects.c | 1 +
 builtin/prune.c| 1 +
 builtin/rev-list.c | 1 +
 revision.c | 3 ++-
 revision.h | 1 +
 t/t4202-log.sh | 4 
 t/t8002-blame.sh   | 4 
 7 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index b059b86aee..c409fa25d6 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3108,6 +3108,7 @@ static void get_object_list(int ac, const char **av)
 
repo_init_revisions(the_repository, , NULL);
save_commit_buffer = 0;
+   revs.allow_exclude_promisor_objects_opt = 1;
setup_revisions(ac, av, , NULL);
 
/* make sure shallows are read */
diff --git a/builtin/prune.c b/builtin/prune.c
index 41230f8215..11284d0bf3 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -120,6 +120,7 @@ int cmd_prune(int argc, const char **argv, const char 
*prefix)
save_commit_buffer = 0;
read_replace_refs = 0;
ref_paranoia = 1;
+   revs.allow_exclude_promisor_objects_opt = 1;
repo_init_revisions(the_repository, , prefix);
 
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 5064d08e1b..2880ed37e3 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -374,6 +374,7 @@ int cmd_rev_list(int argc, const char **argv, const char 
*prefix)
git_config(git_default_config, NULL);
repo_init_revisions(the_repository, , prefix);
revs.abbrev = DEFAULT_ABBREV;
+   revs.allow_exclude_promisor_objects_opt = 1;
revs.commit_format = CMIT_FMT_UNSPECIFIED;
revs.do_not_die_on_missing_tree = 1;
 
diff --git a/revision.c b/revision.c
index a1ddb9e11c..28fb2a70cd 100644
--- a/revision.c
+++ b/revision.c
@@ -2138,7 +2138,8 @@ static int handle_revision_opt(struct rev_info *revs, int 
argc, const char **arg
revs->limited = 1;
} else if (!strcmp(arg, "--ignore-missing")) {
revs->ignore_missing = 1;
-   } else if (!strcmp(arg, "--exclude-promisor-objects")) {
+   } else if (revs->allow_exclude_promisor_objects_opt &&
+  !strcmp(arg, "--exclude-promisor-objects")) {
if (fetch_if_missing)
BUG("exclude_promisor_objects can only be used when 
fetch_if_missing is 0");
revs->exclude_promisor_objects = 1;
diff --git a/revision.h b/revision.h
index 1cd0c4b200..0d2abc2d36 100644
--- a/revision.h
+++ b/revision.h
@@ -156,6 +156,7 @@ struct rev_info {
do_not_die_on_missing_tree:1,
 
/* for internal use only */
+   allow_exclude_promisor_objects_opt:1,
exclude_promisor_objects:1;
 
/* Diff flags */
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 153a506151..819c24d10e 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -1703,4 +1703,8 @@ test_expect_success 'log --source paints symmetric 
ranges' '
test_cmp expect actual
 '
 
+test_expect_success '--exclude-promisor-objects does not BUG-crash' '
+   test_must_fail git log --exclude-promisor-objects source-a
+'
+
 test_done
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index 380e1c1054..eea048e52c 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -118,4 +118,8 @@ test_expect_success '--no-abbrev works like --abbrev=40' '
check_abbrev 40 --no-abbrev
 '
 
+test_expect_success '--exclude-promisor-objects does not BUG-crash' '
+   test_must_fail git blame --exclude-promisor-objects one
+'
+
 test_done
-- 
2.19.1.568.g152ad8e336-goog