← 输入框|github.com|刷新
Skip to content

**fix(index): entries, blobs aur submodules ko literal path se remove karo** - #2329

Open
Keerthana-64 wants to merge 1 commit into
gitpython-developers:mainfrom
Keerthana-64:index-remove-literal-paths
Open

Keerthana-64 wants to merge 1 commit into
gitpython-developers:mainfrom
Keerthana-64:index-remove-literal-paths

Conversation

@Keerthana-64

Copy link
Copy Markdown
Contributor

Problem: IndexFile.remove() entries, blobs aur submodules ko bhi pathspec ki tarah git rm ko bhejta tha, toh Git unke naam mein globs expand kar deta tha. Matlab *.txt naam ki entry hatao toh a.txt, b.txt bhi chale jaate the, aur :(glob)** hatao toh saari tracked files, working_tree=True ke saath disk se bhi. Submodule.remove() aur Submodule.move(module=False) mein bhi yahi issue tha, submodule path * ho toh sab kuch delete ke liye stage ho jaata tha.

Fix: Entry, blob aur submodule paths ke aage :(literal) laga diya. Path strings ka glob behaviour same hai. Submodule callers ab apni index entry pass karte hain.

Edge case: Agar GIT_LITERAL_PATHSPECS=1 set hai, toh in items ka remove "did not match any files" pe fail hoga aur kuch nahi hatega.

Tests: 3 naye regression tests, fix se pehle fail aur baad mein pass, CLI aur Gix dono backends pe. Linters sab pass. 108 purane failures unpatched tree pe bhi hain (shallow clone mein tags missing hain).

Kyun: Maine khud yeh issue dhoondha. Koi tool jo untrusted repo ko index.remove ya Submodule.remove se clean up karta hai, woh unrelated files kho sakta tha.

`IndexFile.remove()` passed every item to `git rm` as a pathspec. Path
strings are documented to accept globs, but index entries, blobs and
submodules name one exact path, and Git still expanded glob characters
and pathspec magic in those names. The names are chosen by whoever
authored the repository:

- Removing the entry for a file named `*.txt` also removed `a.txt` and
  `b.txt`.
- Removing the entry for `:(glob)**` removed every tracked path, and with
  `working_tree=True` deleted those files from disk.

`Submodule.remove()` (for a submodule that is not checked out, or with
`module=False`) and `Submodule.move(module=False)` passed the
`.gitmodules` path string to the same call with `force=True`. A
superproject declaring a submodule at path `*` therefore had every
tracked file staged for deletion and the index written. The neighboring
`git rm` and `git mv` calls in `Submodule` already run with
`GIT_LITERAL_PATHSPECS=1`.

Prefix the paths of entry, blob and submodule items with Git's
`:(literal)` pathspec magic and leave path strings unchanged, so a mixed
call keeps the documented glob behavior for its strings. The submodule
callers now pass their index entry. `git mv` reads its sources
literally, so `IndexFile.move()` needs no change. `git rm` has no native
Gix handler and runs through the CLI on both backends, so
`doc/gix-backend.md` is unchanged.

Limitation: when a caller exports `GIT_LITERAL_PATHSPECS=1`, Git does not
parse pathspec magic. Removing an entry, blob or submodule then fails
with "did not match any files" and removes nothing; path strings stay
literal in that environment as before.

Add a `remove-literal` scenario to `tests/fixtures/index.sh`, a
`glob-path` scenario to `tests/fixtures/submodule-special.sh`, and
regression tests in `test/test_index.py` and `test/test_submodule.py`.
The three new test cases fail before the change and pass after it with
both `GIT_PYTHON_BACKEND=cli` and `GIT_PYTHON_BACKEND=gix` (Git 2.52.0,
GixPython 0.3.0, Python 3.11.17, macOS). Full suites with the change:
CLI 1,884 passed and Gix 1,987 passed. Each run also had 108 failures,
and the same 108 tests fail on the unpatched tree. They need history and
tags such as `0.1.6` and `0.3.2.1`, which the shallow local clone lacks.
`ruff check`, `ruff format --check`, `mypy --python-version=3.11`,
`basedpyright --warnings`, ShellCheck and `git diff --check` pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant