Skip to content

.gitignore entries are ignored when the root path matched one of the entries #1964

@mgorny

Description

@mgorny

While installing nbclassic-1.3.0 from a source distribution, different files would be installed to the system, depending on the directory to which the distribution was unpacked. After some investigation in jupyter/nbclassic#336, we've determine that Hatchling does not respect (the remaining) .gitignore patterns if the project root matched a single .gitignore entry.

Please consider the following reproducer:

cat > pyproject.toml <<-EOF
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "foo"
version = "0"

[tool.hatch.build.targets.sdist]
artifacts = ["foo/data/test.txt"]
EOF
cat > .gitignore <<-EOF
foo/data/test.txt
dist/
EOF
mkdir -p foo/data
> foo/__init__.py
> foo/data/test.txt

Building in the git repository works as expected:

$ python -m build
* Creating isolated environment: virtualenv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for sdist...
* Building sdist...
* Building wheel from sdist
* Creating isolated environment: virtualenv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for wheel...
* Building wheel...
Successfully built foo-0.tar.gz and foo-0-py2.py3-none-any.whl
$ unzip -l dist/foo-0-py2.py3-none-any.whl 
Archive:  dist/foo-0-py2.py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  02-02-2020 00:00   foo/__init__.py
       43  02-02-2020 00:00   foo-0.dist-info/METADATA
      105  02-02-2020 00:00   foo-0.dist-info/WHEEL
      250  02-02-2020 00:00   foo-0.dist-info/RECORD
---------                     -------
      398                     4 files

However, building inside the dist subdirectory causes the .gitignore entry for foo/data/test.txt to be ignored:

$ cd dist
$ tar -xf foo-0.tar.gz
$ cd foo-0
$ python -m build -w
* Creating isolated environment: virtualenv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for wheel...
* Building wheel...
Successfully built foo-0-py2.py3-none-any.whl
$ unzip -l dist/foo-0-py2.py3-none-any.whl 
Archive:  dist/foo-0-py2.py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  02-02-2020 00:00   foo/__init__.py
        0  02-02-2020 00:00   foo/data/test.txt
       43  02-02-2020 00:00   foo-0.dist-info/METADATA
      105  02-02-2020 00:00   foo-0.dist-info/WHEEL
      321  02-02-2020 00:00   foo-0.dist-info/RECORD
---------                     -------
      469                     5 files

Note that if I remove the entry for dist/, everything starts working again:

$ sed -i -e /dist/d .gitignore
$ python -m build -w
* Creating isolated environment: virtualenv+pip...
* Installing packages in isolated environment:
  - hatchling
* Getting build dependencies for wheel...
* Building wheel...
Successfully built foo-0-py2.py3-none-any.whl
$ unzip -l dist/foo-0-py2.py3-none-any.whl 
Archive:  dist/foo-0-py2.py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  02-02-2020 00:00   foo/__init__.py
       43  02-02-2020 00:00   foo-0.dist-info/METADATA
      105  02-02-2020 00:00   foo-0.dist-info/WHEEL
      250  02-02-2020 00:00   foo-0.dist-info/RECORD
---------                     -------
      398                     4 files

This is particularly problematic, because as a package author you really can't predict (nor you should try to) what directories will users use to build your package from source. Furthermore, it is hard even to notice that something went wrong, as the effect is only additional files being installed.

The problem seems to have been introduced in #1643 + #1791, CC @jameshilliard.

Reproduced with Hatchling 1.27.0, on Python 3.13.3.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions