Re: [PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-03-03 Thread Greg Price
On Wed, Feb 27, 2013 at 12:20:07PM -0800, Junio C Hamano wrote:
 Without --all the command considers only the annotated tags to
 base the descripion on, and with --all, a ref that is not
 annotated tags can be used as a base, but with a lower priority (if
 an annotated tag can describe a given commit, that tag is used).
 
 So naïvely I would expect --all and --match to base the
 description on refs that match the pattern without limiting the
 choice of base to annotated tags, and refs that do not match the
 given pattern should not appear even as the last resort.  It appears
 to me that the current situation is (3).

Hmm.  It seems to me that --all says two things:

 (a) allow unannotated (rather than only annotated)

 (b) allow refs of any name (rather than only tags)

With --match, particularly because the pattern always refers only to
tags, (b) is obliterated, and your proposed semantics are (a) plus a
sort of inverse of (b):

 (c) allow only refs matching the pattern

which is what --match means alone.  But if what we are going for is
(a) and (c), then we don't need --all for (a) -- we can get
precisely that with --tags.  So these semantics make --all --match=PAT
equivalent to --tags --match=PAT.

Given that, I think the user is better off if we reject --all
--match with an error message -- and perhaps the error message should
advise them to use --tags instead.  Otherwise we have --all
telling us (b) as well as (a), and --match countermanding (b) and
going precisely the other direction to (c).  If the user has written
that by hand, then they may be confused, and if the command line was
generated, perhaps called from a script, then I fear a bug in the
script is likely, what with the conflicting expectations expressed by
--all and --match.

Patch below to suggest --tags in the error message.

Greg
From 66f985b2510c870e62e313732de4b6709894b074 Mon Sep 17 00:00:00 2001
From: Greg Price pr...@mit.edu
Date: Sun, 3 Mar 2013 12:19:57 -0800
Subject: [PATCH] describe: Better error message on --all --match

The reason they conflict is that --all means
 (a) allow unannotated, and
 (b) allow refs of any name (rather than only tags),
while --match contradicts (b) and goes further to
 (c) allow only tags matching pattern.

If what the user wants is (a) and (c), they can use --tags to get (a)
without (b).
---
 builtin/describe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/describe.c b/builtin/describe.c
index 2ef3f10..6581c40 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -436,7 +436,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		die(_(--long is incompatible with --abbrev=0));
 
 	if (pattern  all)
-		die(_(--match is incompatible with --all));
+		die(_(--all conflicts with --match; do you mean --tags?));
 
 	if (contains) {
 		const char **args = xmalloc((7 + argc) * sizeof(char *));
-- 
1.7.11.3



Re: [PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-03-03 Thread Junio C Hamano
Greg Price pr...@mit.edu writes:

 On Wed, Feb 27, 2013 at 12:20:07PM -0800, Junio C Hamano wrote:
 Without --all the command considers only the annotated tags to
 base the descripion on, and with --all, a ref that is not
 annotated tags can be used as a base, but with a lower priority (if
 an annotated tag can describe a given commit, that tag is used).
 
 So naïvely I would expect --all and --match to base the
 description on refs that match the pattern without limiting the
 choice of base to annotated tags, and refs that do not match the
 given pattern should not appear even as the last resort.  It appears
 to me that the current situation is (3).

 Hmm.  It seems to me that --all says two things:

  (a) allow unannotated (rather than only annotated)

  (b) allow refs of any name (rather than only tags)

 With --match, particularly because the pattern always refers only to
 tags, (b) is obliterated, and your proposed semantics are (a) plus a
 sort of inverse of (b):

  (c) allow only refs matching the pattern

I would think it is more like only (a), without changing the
documented semantics of what '--all' and '--match' are by adding (b)
or (c).

I do not think in the longer term it is wrong per-se to change the
semantics of --match from the documented Only consider tags
matching the pattern to Only consider refs matching the pattern,
and such a change can and should be made as a separate patch
describe: loosen --match to allow any ref, not just tags on top of
the patch I sent which was meant to be bugfix-only.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-03-03 Thread Greg Price
On Sun, Mar 03, 2013 at 01:15:21PM -0800, Junio C Hamano wrote:
 Greg Price pr...@mit.edu writes:
  It seems to me that --all says two things:
 
   (a) allow unannotated (rather than only annotated)
 
   (b) allow refs of any name (rather than only tags)
 
  With --match, particularly because the pattern always refers only to
  tags, (b) is obliterated, and your proposed semantics are (a) plus a
  sort of inverse of (b):
 
   (c) allow only refs matching the pattern
 
 I would think it is more like only (a), without changing the
 documented semantics of what '--all' and '--match' are by adding (b)
 or (c).

Perhaps I'm confused somehow?  I believe (a) and (b) together are the
documented semantics of what '--all' is.  And I believe (c), which
contradicts (b) and indeed goes in the opposite direction, is the
documented semantics of what '--match' is.

Certainly we could choose to resolve the conflict by saying that
'--match' overrides '--all', so that '--all' plus '--match' means
(a)+(c).  I believe that's what you suggested.

I think it would be preferable to recognize the conflict and let the
user sort out what they actually mean, because if they (or their
script) gave these options together then I think there's a substantial
likelihood that they are confused or their script is buggy.  If they
mean (a)+(c), they can get it more clearly with '--tag --match'.



 I do not think in the longer term it is wrong per-se to change the
 semantics of --match from the documented Only consider tags
 matching the pattern to Only consider refs matching the pattern,
 and such a change can and should be made as a separate patch
 describe: loosen --match to allow any ref, not just tags on top of
 the patch I sent which was meant to be bugfix-only.

Yeah, that could be useful.  What form of pattern would you suggest
that the new '--match' accept?  The obvious, and unambiguous, form of
pattern is glob patterns on the full ref name, as with 'for-each-ref'.
Those are a little unwieldy for interactive use, but are perfect for a
script.  And probably 'describe --match' itself already makes the most
sense in a scripted context, as for interactive use one can go into
'gitk' or 'git log --oneline --decorate' or the like and find out the
same information plus more detail.

Particularly when handling both tags and other refs, I can also
imagine wanting to specify a disjunction of several patterns.  So we
might want to accept the option several times cumulatively.

I'd worry about changing the semantics of existing 'describe --match'
invocations in people's scripts, etc.  Perhaps we'd give it a new name
like '--match-ref'.  Or we could say something like, if it starts with
refs/ it's a pattern on the whole refname, else it's a pattern on
just the tag name, and accept that if someone has a ref called
refs/tags/refs/foo and was finding it with 'describe --match' then
that will break until they edit the pattern.

Cheers,
Greg
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-02-28 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 I am not sure if this is (1) behaviour is sometimes useful in
 narrow cases but is not explained well, (2) behaviour does not
 make sense in any situation, or (3) the combination can make sense
 if corrected, but the current behaviour is buggy.  If it is (2) or
 (3), I think it makes sense to forbid the combination. Also, if it
 is (3), we should later come up with an improved behaviour and then
 re-enable the combination.

 Without --all the command considers only the annotated tags to
 base the descripion on, and with --all, a ref that is not
 annotated tags can be used as a base, but with a lower priority (if
 an annotated tag can describe a given commit, that tag is used).

 So naïvely I would expect --all and --match to base the
 description on refs that match the pattern without limiting the
 choice of base to annotated tags, and refs that do not match the
 given pattern should not appear even as the last resort.  It appears
 to me that the current situation is (3).

 Will queue and cook in 'next'; thanks.

A fix to the broken semantics may look like this.  There are a few
points to note:

 * The local variable names is_tag and might_be_tag were
   inconsistent with the rest of the program, where the global
   variable tags is used to mean the user gave --tags to allow
   lightweight ones to be used.  By that definition of the tag, a
   ref under refs/tags/ *is* a tag, and a ref that peels to a
   different object is an annotated tag.  These two variable names
   have been fixed.

 * The function returns early for a ref outside refs/tags/ when
   --all is not given with or without this patch.  At the end of
   the function, it also returned when (!all  !prio), but prio
   becomes zero only when the ref is outside refs/tags/ (or the tag
   does not match the pattern) in the original code.  With this
   patch, we reject refs outside refs/tags/ early when --all is
   not given, so the last-minute check before add_to_known_names()
   becomes unnecessary (hence removed).

 * If somebody is crazy enough to have an annotated tag under
   refs/heads/, the code would treat it as an annotated tag and
   assign prio==2 to it, with or without this patch.  We may want to
   tighten this further by checking with is_tag, but this patch does
   not do anything about it; I wanted it to focus on only one bug,
   i.e. interaction between --all and --match=pattern.

 * When --tags is not given, we still give an unannotated tag to
   add_to_known_names(), only to issue a hint when the given commit
   is not describable with annotated tags but it could be described
   if --tags were given.  I think this is optimizing for the wrong
   case, and wasting resources.


 builtin/describe.c | 41 -
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/builtin/describe.c b/builtin/describe.c
index 04c185b..b2b740d 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -137,40 +137,39 @@ static void add_to_known_names(const char *path,
 
 static int get_name(const char *path, const unsigned char *sha1, int flag, 
void *cb_data)
 {
-   int might_be_tag = !prefixcmp(path, refs/tags/);
+   int is_tag = !prefixcmp(path, refs/tags/);
unsigned char peeled[20];
-   int is_tag, prio;
+   int is_annotated, prio;
 
-   if (!all  !might_be_tag)
+   /* Reject anything outside refs/tags/ unless --all */
+   if (!all  !is_tag)
return 0;
 
+   /* Accept only tags that match the pattern, if given */
+   if (pattern  (!is_tag || fnmatch(pattern, path + 10, 0)))
+   return 0;
+
+   /* Is it annotated? */
if (!peel_ref(path, peeled)) {
-   is_tag = !!hashcmp(sha1, peeled);
+   is_annotated = !!hashcmp(sha1, peeled);
} else {
hashcpy(peeled, sha1);
-   is_tag = 0;
+   is_annotated = 0;
}
 
-   /* If --all, then any refs are used.
-* If --tags, then any tags are used.
-* Otherwise only annotated tags are used.
+   /*
+* By default, we only use annotated tags, but with --tags
+* we fall back to lightweight ones (even without --tags,
+* we still remember lightweight ones, only to give hints
+* in an error message).  --all allows any refs to be used.
 */
-   if (might_be_tag) {
-   if (is_tag)
-   prio = 2;
-   else
-   prio = 1;
-
-   if (pattern  fnmatch(pattern, path + 10, 0))
-   prio = 0;
-   }
+   if (is_annotated)
+   prio = 2;
+   else if (is_tag)
+   prio = 1;
else
prio = 0;
 
-   if (!all) {
-   if (!prio)
-   return 0;
-   }
add_to_known_names(all ? path + 5 : path + 10, peeled, prio, sha1);
return 0;
 }
--
To 

Re: [PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-02-27 Thread Junio C Hamano
Greg Price pr...@mit.edu writes:

 Currently when --all is passed, the effect of --match is only
 to demote non-matching tags to be treated like non-tags.  This
 is puzzling behavior and not consistent with the documentation,
 especially with the suggested usage of avoiding information leaks.
 The combination of --all and --match is an oxymoron anyway, so
 just forbid it.

I am not sure if this is (1) behaviour is sometimes useful in
narrow cases but is not explained well, (2) behaviour does not
make sense in any situation, or (3) the combination can make sense
if corrected, but the current behaviour is buggy.  If it is (2) or
(3), I think it makes sense to forbid the combination. Also, if it
is (3), we should later come up with an improved behaviour and then
re-enable the combination.

Without --all the command considers only the annotated tags to
base the descripion on, and with --all, a ref that is not
annotated tags can be used as a base, but with a lower priority (if
an annotated tag can describe a given commit, that tag is used).

So naïvely I would expect --all and --match to base the
description on refs that match the pattern without limiting the
choice of base to annotated tags, and refs that do not match the
given pattern should not appear even as the last resort.  It appears
to me that the current situation is (3).

Will queue and cook in 'next'; thanks.


 Signed-off-by: Greg Price pr...@mit.edu
 ---
 This should be applied after the preceding patch; I mistakenly omitted
 the '1/2' in its subject line.

  Documentation/git-describe.txt | 3 ++-
  builtin/describe.c | 3 +++
  2 files changed, 5 insertions(+), 1 deletion(-)

 diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
 index 711040d..fd5d8f2 100644
 --- a/Documentation/git-describe.txt
 +++ b/Documentation/git-describe.txt
 @@ -83,7 +83,8 @@ OPTIONS
  --match pattern::
   Only consider tags matching the given `glob(7)` pattern,
   excluding the refs/tags/ prefix.  This can be used to avoid
 - leaking private tags from the repository.
 + leaking private tags from the repository.  This option is
 + incompatible with `--all`.
  
  --always::
   Show uniquely abbreviated commit object as fallback.
 diff --git a/builtin/describe.c b/builtin/describe.c
 index 04c185b..90a72af 100644
 --- a/builtin/describe.c
 +++ b/builtin/describe.c
 @@ -435,6 +435,9 @@ int cmd_describe(int argc, const char **argv, const char 
 *prefix)
   if (longformat  abbrev == 0)
   die(_(--long is incompatible with --abbrev=0));
  
 + if (pattern  all)
 + die(_(--match is incompatible with --all));
 +
   if (contains) {
   const char **args = xmalloc((7 + argc) * sizeof(char *));
   int i = 0;
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] describe: Exclude --all --match=PATTERN

2013-02-24 Thread Greg Price
Currently when --all is passed, the effect of --match is only
to demote non-matching tags to be treated like non-tags.  This
is puzzling behavior and not consistent with the documentation,
especially with the suggested usage of avoiding information leaks.
The combination of --all and --match is an oxymoron anyway, so
just forbid it.

Signed-off-by: Greg Price pr...@mit.edu
---
This should be applied after the preceding patch; I mistakenly omitted
the '1/2' in its subject line.

 Documentation/git-describe.txt | 3 ++-
 builtin/describe.c | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 711040d..fd5d8f2 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -83,7 +83,8 @@ OPTIONS
 --match pattern::
Only consider tags matching the given `glob(7)` pattern,
excluding the refs/tags/ prefix.  This can be used to avoid
-   leaking private tags from the repository.
+   leaking private tags from the repository.  This option is
+   incompatible with `--all`.
 
 --always::
Show uniquely abbreviated commit object as fallback.
diff --git a/builtin/describe.c b/builtin/describe.c
index 04c185b..90a72af 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -435,6 +435,9 @@ int cmd_describe(int argc, const char **argv, const char 
*prefix)
if (longformat  abbrev == 0)
die(_(--long is incompatible with --abbrev=0));
 
+   if (pattern  all)
+   die(_(--match is incompatible with --all));
+
if (contains) {
const char **args = xmalloc((7 + argc) * sizeof(char *));
int i = 0;
-- 
1.7.11.3
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html