feat(updating): propagate exec bit on new template files when core.fileMode=false#2640
Open
willemkokke wants to merge 1 commit intocopier-org:masterfrom
Open
Conversation
…leMode=false Files newly introduced by the template on `copier update` were not yet tracked in the destination's index, so the existing `_sync_git_index_executable_bit` short-circuited for them. With `core.fileMode=false` (Windows default) the user's eventual `git add` would record `100644` regardless of the template's intended mode, silently losing the executable bit. When an untracked file with desired exec bits is rendered into a `core.fileMode=false` repo, copier now registers an intent-to-add entry via `git add --intent-to-add` and rewrites its mode to `100755` via `update-index --cacheinfo`. The empty blob is preserved, so the user's eventual `git add` replaces it with the file's actual content while preserving `100755`. The intent-to-add marker (`A` in `git status`) is also a more accurate signal than `??` for files that are deliberate template output rather than random untracked content. When `core.fileMode=true`, copier still leaves new files untracked — git would have picked up the on-disk chmod naturally, and pre-staging would be inconsistent with copier's normal "leave rendered changes unstaged for user review" behavior. Closes copier-org#2630
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2640 +/- ##
==========================================
- Coverage 97.15% 97.10% -0.06%
==========================================
Files 60 60
Lines 7101 7185 +84
==========================================
+ Hits 6899 6977 +78
- Misses 202 208 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #2630. Follow-up to #2605.
#2605 fixed executable-bit propagation for files that already exist in the destination. Files introduced by the template for the first time on
copier updatewere still affected whencore.fileMode=false:script.shwith100755in the index.core.fileMode=false(Windows default).chmods it on disk (invisible to git withfileMode=false), then calls_sync_git_index_executable_bit— which short-circuited because the file is untracked.git add script.shrecords100644because git ignores on-disk mode withfileMode=false. Exec bit lost.Changes
copier/_main.py—_sync_git_index_executable_bit:For untracked files that should be executable, run
git add --intent-to-add <path>to register an empty index entry, then fall through to the existing--cacheinfopath to set the mode to100755. The user's eventualgit addreplaces the empty blob with the file's actual content while preserving the mode bit. The intent-to-add marker (Aingit status) is also a more accurate signal than??for files that are deliberate template output.git addwould record100644either way).core.fileMode=true(git picks up the on-disk chmod naturally — pre-staging would be inconsistent with copier's "leave changes unstaged for user review" behavior).tests/test_updatediff.py— 3 new tests:test_update_introduces_new_executable_file[True|False]100755onfileMode=false; file stays untracked onfileMode=truetest_update_introduces_new_non_executable_file[True|False]test_update_introduces_new_executable_file_then_user_commitscore.fileMode=false: copier update →git add→git commit→ committed tree records100755and the file's actual content. The template setup usesgit update-index --chmod=+x(rather thanPath.chmod) so the test runs identically on every platform — Linux, macOS, and Windows.Test plan