Jeff King <peff@xxxxxxxx> writes: > On Fri, Jan 18, 2019 at 11:58:01AM -0500, Jeff King wrote: > >> Now, on to the actual bug. The simplest reproduction is: >> >> (echo "[attr]foo bar"; echo "* foo") >.gitattributes >> git check-attr foo file > > Actually, even simpler is to just "binary", which is pre-defined as a > macro. :) > >> which should report "foo" as set. This bisects to 60a12722ac (attr: >> remove maybe-real, maybe-macro from git_attr, 2017-01-27), and it seems >> like an unintentional regression there. I haven't yet poked into that >> commit to see what the fix will look like. > > So here's the fix I came up with. +cc Duy, as this is really tangled > with his older 06a604e670. > > -- >8 -- > Subject: [PATCH] attr: do not mark queried macros as unset > > Since 60a12722ac (attr: remove maybe-real, maybe-macro from git_attr, > 2017-01-27), we will always mark an attribute macro (e.g., "binary") > that is specifically queried for as "unspecified", even though listing > _all_ attributes would display it at set. E.g.: > > $ echo "* binary" >.gitattributes > > $ git check-attr -a file > file: binary: set > file: diff: unset > file: merge: unset > file: text: unset > > $ git check-attr binary file > file: binary: unspecified > > The problem stems from an incorrect conversion of the optimization from > 06a604e670 (attr: avoid heavy work when we know the specified attr is > not defined, 2014-12-28). There we tried in collect_some_attrs() to > avoid even looking at the attr_stack when the user has asked for "foo" > and we know that "foo" did not ever appear in any .gitattributes file. > > It used a flag "maybe_real" in each attribute struct, where "real" meant > that the attribute appeared in an actual file (we have to make this > distinction because we also create an attribute struct for any names > that are being queried). But as explained in that commit message, the > meaning of "real" was tangled with some special cases around macros. > > When 06a604e670 later refactored the macro code, it dropped maybe_real I think 60a12722ac is what you meant here. > entirely. This missed the fact that "maybe_real" could be unset for two > reasons: because of a macro, or because it was never found during > parsing. This had two results: > > - the optimization in collect_some_attrs() ceased doing anything > meaningful, since it no longer kept track of "was it found during > parsing" > > - worse, it actually kicked in when the caller _did_ ask about a macro > by name, causing us to mark it as unspecified