All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Hurka <david.hurka@mailbox.org>
To: git@vger.kernel.org
Subject: Bug: Documentation and behavior mismatch in and between git-archive and gitattributes/git-check-attr.
Date: Thu, 23 Sep 2021 16:52:22 +0200	[thread overview]
Message-ID: <22364178.6Emhk5qWAg@doro> (raw)

Hello all,

in https://github.com/Kentzo/git-archive-all/issues/87 I reported a problem 
which turns out to be more likely a problem in git.

The documentation of `gitattributes` says:

> The rules [mostly follow .gitignore], with a few exceptions:
> * [...]
> * patterns that match a directory do not recursively match paths
>   inside that directory (so using the trailing-slash path/ syntax
>   is pointless in an attributes file; use path/** instead)

This means to me, that patterns may match _directories_ instead of the files 
in them.

So, if I have a /.gitattributes file like this:

> LICENSES/ export-ignore

I expect the whole directory /LICENSES/ to be matched, so a tool like 
`git-archive` skips it when creating an archive.

However, if I have a /.gitattributes file like this:

> LICENSES/** export-ignore

I expect the directory itself not to be matched, but all files inside it, so a 
tool like `git-archive` adds an empty /LICENSES/ directory to the archive.

`git-archive` actually behaves like this.

However, `git-check-attr` does not behave like this. In the second example, it 
will list `export-ignore` matching on every file inside /LICENSES/. But in the 
first example, it will list `export-ignore` matching nowhere. This leads to 
the problem where `git-archive-all` wrongly exports the whole /LICENSES/ 
directory.

The documentation for `gitattributes` says for `export-ignore`:

> `export-ignore`
>   Files and directories with the attribute `export-ignore`
>   won’t be added to archive files.

For most other attributes it does not include directories, because they do not 
make sense for directories.

---

I think the solution is like this:

1. Change the documentation of `gitattributes` to:

> The rules [mostly follow .gitignore], with a few exceptions:
> * [...]
> * patterns that match a directory do not recursively match paths
>   inside that directory. (Since most attributes are only useful for
>   files, the path/ syntax is probably incorrect; use path/** instead.)

2. Change git-check-attr to make patterns like path/ match directories. At 
least, for attributes like `export-ignore` this should be changed, but I think 
the correct solution is to change it for all attributes.

---

Below is a shell script to reproduce the problem.

```
mkdir test_attributes
cd test_attributes
git init -b master
mkdir include dont-include-1 dont-include-2 dont-include-3
touch include/a.txt dont-include-1/b.txt dont-include-2/c.txt dont-include-3/
d.txt
echo dont-include-1/ export-ignore >>.gitattributes
echo dont-include-2/** export-ignore >> .gitattributes
echo dont-include-3 export-ignore >>.gitattributes
git add -A
git commit -m "Test gitattributes"

git archive --output ../test_attributes.zip HEAD
zipinfo ../test_attributes.zip

git check-attr export-ignore * */*
```

This is the output which I get with git version 2.33.0.752.gd22421fcc6:

> $ git archive --output ../test_attributes.zip HEAD
> $ zipinfo ../test_attributes.zip
> Archive:  ../test_attributes.zip
> Zip file size: 584 bytes, number of entries: 4
> -rw----     0.0 fat       94 tx defN 21-Sep-23 16:37 .gitattributes
> drwx---     0.0 fat        0 bx stor 21-Sep-23 16:37 dont-include-2/
> drwx---     0.0 fat        0 bx stor 21-Sep-23 16:37 include/
> -rw----     0.0 fat        0 tx stor 21-Sep-23 16:37 include/a.txt
> 4 files, 94 bytes uncompressed, 46 bytes compressed:  51.1%
> 
> $ git check-attr export-ignore * */*
> dont-include-1: export-ignore: unspecified
> dont-include-2: export-ignore: unspecified
> dont-include-3: export-ignore: set
> include: export-ignore: unspecified
> dont-include-1/b.txt: export-ignore: unspecified
> dont-include-2/c.txt: export-ignore: set
> dont-include-3/d.txt: export-ignore: unspecified
> include/a.txt: export-ignore: unspecified

Note how `dont-include-2/** export-ignore` caused an empty directory to be 
created. This is problematic for my workflow.

`dont-include-3 export-ignore` yields the desired results here, but I think it 
is not always an alternative, since the missing trailing slash makes the rule 
apply to files too. For example in this repository structure:

> - a/
>   - dont-include-3/
>     - a.txt
> - b/
>   - dont-include-3/
>     - b.txt
> - dont-include-3

I could not use the glob syntax `**/dont-include-3 export-ignore` to skip only 
the two _directories_ with a.txt and b.txt, because the _file_ dont-include-3 
would also be skipped.

---

I am generally available for submitting patches to fix this issue. Let me know 
what you think. :)

Cheers, David




                 reply	other threads:[~2021-09-23 14:52 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=22364178.6Emhk5qWAg@doro \
    --to=david.hurka@mailbox.org \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.