{"thread":{"id":"52301","subject":"GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","startedAt":"2019-11-20T16:44:56Z","lastAt":"2019-11-22T06:59:21Z","messageCount":6,"participants":["M Lewis","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"386645","messageId":"01e0a4ab-d809-d968-5671-b731438c2bc4@gmail.com","threadId":"52301","inReplyTo":null,"subject":"GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"M Lewis","fromEmail":"picevio@gmail.com","sentAt":"2019-11-20T16:44:52Z","receivedAt":"2019-11-20T16:44:56Z","isPatch":false,"sender":{"key":"picevio@gmail.com","avatar":null},"body":"When running 'git archive', the .gitattributes file is used to determine \npaths that should be ignored when building the archive by using \n'export-ignore'.\nBut it would be useful to include certain sub-paths in the ignored path.\n\nFor example, say I have folders like these\n     /all_useful                  # this entire sub directory is needed \nin the archive\n     /mostly_unuseful             # there are many sub directories in \nhere to ignore\n/mostly_unuseful/needed_a    # but these specific sub directories are \ndesired in the archive\n/mostly_unuseful/needed_b\n\nThe git-attribute document says a dash '-' prefix should unset the \nattribute. It should work with 'export-ignore'\n\nSo if I want for example '/mostly_unuseful/needed_a' in my archive, I \nshould be able to specify that\nin my .gitattributes file like this:\n\n\n     /mostly_unuseful                  export-ignore # do not archive\n/mostly_unuseful/needed_a -export-ignore # do add to archive\n/mostly_unuseful/needed_b    -export-ignore # do add to archive\n\nThank you\n\n"},{"id":"386703","messageId":"20191121075837.GA30966@sigill.intra.peff.net","threadId":"52301","inReplyTo":"01e0a4ab-d809-d968-5671-b731438c2bc4@gmail.com","subject":"Re: GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-21T07:58:37Z","receivedAt":"2019-11-21T07:58:40Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Nov 20, 2019 at 08:44:52AM -0800, M Lewis wrote:\n\n> When running 'git archive', the .gitattributes file is used to determine\n> paths that should be ignored when building the archive by using\n> 'export-ignore'.\n> But it would be useful to include certain sub-paths in the ignored path.\n\nYeah, that seems like a reasonable goal, and I think we can make it\nwork, but the syntax is slightly different.\n\n> The git-attribute document says a dash '-' prefix should unset the\n> attribute. It should work with 'export-ignore'\n> \n> So if I want for example '/mostly_unuseful/needed_a' in my archive, I\n> should be able to specify that in my .gitattributes file like this:\n> \n>     /mostly_unuseful              export-ignore # do not archive\n>     /mostly_unuseful/needed_a    -export-ignore # do add to archive\n>     /mostly_unuseful/needed_b    -export-ignore # do add to archive\n\nIt doesn't work because the attributes are not applied recursively[1];\nthey are applied to the path you specified. By putting the attribute on\n\"mostly_unuseful\", that doesn't say anything about \"needed_a\" (from the\nperspective of the attributes system). So removing it from that path\nlikewise does nothing; the attribute is still set on the directory.\n\nInstead, if you write it like this:\n\n  /mostly_unuseful/**        export-ignore\n  /mostly_unuseful/needed_a -export-ignore\n  /mostly_unuseful/needed_b -export-ignore\n\nThen the attributes are applied directly to the file paths in the first\nline, and the subsequent lines counteract them. This does mean that the\nsubdirectory itself isn't marked as export-ignore, and will always be\nincluded (as an empty directory if need be, though of course in your\nexample we do actually end up with some files in it).\n\nNow obviously there is recursion happening inside git-archive, as it\nwalks the tree. And the current behavior is that it sees the ignored\nsubtree and doesn't walk into it at all. So it _could_ make your\noriginal example work by actually searching within the tree for any\npaths marked -export-ignore, and including the directory if and only if\nit has unignored entries.\n\nI can't offhand think of anything that would break if we started doing\nthat, but I haven't thought too hard. And given that there's already a\nsolution using `**`, it might not be worth it.\n\n-Peff\n\n[1] If you're curious, there's some philosophical discussion about this exact issue in\n    https://public-inbox.org/git/7v1uasg8e0.fsf@alter.siamese.dyndns.org/\n"},{"id":"386722","messageId":"xmqq5zjd8ij2.fsf@gitster-ct.c.googlers.com","threadId":"52301","inReplyTo":"20191121075837.GA30966@sigill.intra.peff.net","subject":"Re: GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-21T13:29:21Z","receivedAt":"2019-11-21T13:29:28Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> Now obviously there is recursion happening inside git-archive, as it\n> walks the tree. And the current behavior is that it sees the ignored\n> subtree and doesn't walk into it at all. So it _could_ make your\n> original example work by actually searching within the tree for any\n> paths marked -export-ignore, and including the directory if and only if\n> it has unignored entries.\n>\n> I can't offhand think of anything that would break if we started doing\n> that,...\n\nIf there is some effect we want to attach to a directory itself\nwithout affecting the paths inside it, the current and original\ndesign lets you express it naturally.  If we make a pattern that\nmatch a directory to recurse, it is still possible to express it,\nbut it is a bit cumbersome, e.g.\n\n\t/directory\twant-to-affect-this\n\t/directory/**\t-want-to-affect-this\n\nI would think.\n\nGit generally does *not* track directories, so in a sense it is\narguable if it even makes sense to think about attaching an\nattribute to a directory itself (as opposed to a non-directory\ninside the directory) in the first place, though.\n\n\n\n"},{"id":"386731","messageId":"1e9e3272-f97b-9944-817f-778deec2e65c@gmail.com","threadId":"52301","inReplyTo":"20191121075837.GA30966@sigill.intra.peff.net","subject":"Re: GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"M Lewis","fromEmail":"picevio@gmail.com","sentAt":"2019-11-21T15:45:44Z","receivedAt":"2019-11-21T15:45:49Z","isPatch":false,"sender":{"key":"picevio@gmail.com","avatar":null},"body":"Jeff,\n\nThank you for taking this on. I tried your suggestion copied below. The \n'needed_a' (and _b) directories appear in the archive but unfortunately \nthey are empty. We need the contents of the directories in the archive.\n\nOn 11/20/2019 11:58 PM, Jeff King wrote:\n> Instead, if you write it like this:\n>\n>    /mostly_unuseful/**        export-ignore\n>    /mostly_unuseful/needed_a -export-ignore\n>    /mostly_unuseful/needed_b -export-ignore\n>\n> ... And given that there's already a\n> solution using `**`, it might not be worth it.\n>\n"},{"id":"386803","messageId":"20191122065441.GA23225@sigill.intra.peff.net","threadId":"52301","inReplyTo":"1e9e3272-f97b-9944-817f-778deec2e65c@gmail.com","subject":"Re: GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-22T06:54:41Z","receivedAt":"2019-11-22T06:54:43Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 21, 2019 at 07:45:44AM -0800, M Lewis wrote:\n\n> Thank you for taking this on. I tried your suggestion copied below. The\n> 'needed_a' (and _b) directories appear in the archive but unfortunately they\n> are empty. We need the contents of the directories in the archive.\n\nAh, I assumed they were files. You should be able to handle that by\nsetting and clearing the attributes using the \"**\" syntax. Something\nlike:\n\n  /subdir/** export-ignore\n  /subdir/keep/ -export-ignore\n  /subdir/keep/** -export-ignore\n\nwould work to re-enable \"one\" and all of its contents. Or if everything\nyou want to toggle is at the top-level of the subdirectory, you can use\n\"*\" to avoid assigning export-ignore to all of the recursive paths in\nthe first place, like:\n\n  /subdir/* export-ignore\n  /subdir/keep/ -export-ignore\n\n-Peff\n"},{"id":"386804","messageId":"20191122065918.GB23225@sigill.intra.peff.net","threadId":"52301","inReplyTo":"xmqq5zjd8ij2.fsf@gitster-ct.c.googlers.com","subject":"Re: GitAttributes feature export-ignore works, but -export-ignore (with dash) should also work","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-22T06:59:18Z","receivedAt":"2019-11-22T06:59:21Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 21, 2019 at 10:29:21PM +0900, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > Now obviously there is recursion happening inside git-archive, as it\n> > walks the tree. And the current behavior is that it sees the ignored\n> > subtree and doesn't walk into it at all. So it _could_ make your\n> > original example work by actually searching within the tree for any\n> > paths marked -export-ignore, and including the directory if and only if\n> > it has unignored entries.\n> >\n> > I can't offhand think of anything that would break if we started doing\n> > that,...\n> \n> If there is some effect we want to attach to a directory itself\n> without affecting the paths inside it, the current and original\n> design lets you express it naturally.  If we make a pattern that\n> match a directory to recurse, it is still possible to express it,\n> but it is a bit cumbersome, e.g.\n> \n> \t/directory\twant-to-affect-this\n> \t/directory/**\t-want-to-affect-this\n> \n> I would think.\n\nI didn't mean teaching the attribute code anything about recursion. You\nconvinced me in the thread I linked that the current rules are just fine\nfor expressing what we want (and especially with \"**\" now it's easy).\nIt's git-archive which does the recursion here, so it could have more\nconvenient semantics for an attribute attached to a directory.\n\n(Though again, I'm happy enough with the solutions I've suggested in\nthis thread).\n\n> Git generally does *not* track directories, so in a sense it is\n> arguable if it even makes sense to think about attaching an\n> attribute to a directory itself (as opposed to a non-directory\n> inside the directory) in the first place, though.\n\nI mostly agree, though in this case if we are exporting to a tarball,\nwhich _does_ care about directories. So the difference between \"don't\nexport foo/\" and \"don't export foo/*\" can be observed in the output. I\ndoubt anybody really cares that much in practice, though (i.e., does\nanybody really want to be able to output empty directories in their\ntarballs?).\n\n-Peff\n"}]}