Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package chezmoi for openSUSE:Factory checked 
in at 2025-11-04 18:41:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/chezmoi (Old)
 and      /work/SRC/openSUSE:Factory/.chezmoi.new.1980 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "chezmoi"

Tue Nov  4 18:41:30 2025 rev:86 rq:1315354 version:2.67.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/chezmoi/chezmoi.changes  2025-10-22 
12:20:58.039307531 +0200
+++ /work/SRC/openSUSE:Factory/.chezmoi.new.1980/chezmoi.changes        
2025-11-04 18:41:58.972481947 +0100
@@ -1,0 +2,17 @@
+Mon Nov  3 17:24:40 UTC 2025 - Filippo Bonazzi <[email protected]>
+
+- Update to version 2.67.0:
+  - Features
+    * feat: Make re-add add and remove entries in exact_ directories
+  - Fixes
+    * fix: Make all template funcs available in diff and merge args
+    * fix: Ignore special-use domains when extracting hostname from /etc/hosts
+    * fix: Fix fromIni | toIni template func round trip with quoted strings
+    * fix: Fix pattern in install script
+  - Documentation
+    * docs: Improve description of --create flag
+    * docs: Update VSCode merge tool instructions to handles spaces in paths
+  - Other
+    * Update documentation for --create option in add.md
+
+-------------------------------------------------------------------

Old:
----
  chezmoi-2.66.1.obscpio

New:
----
  chezmoi-2.67.0.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ chezmoi.spec ++++++
--- /var/tmp/diff_new_pack.g9bK5V/_old  2025-11-04 18:41:59.832518152 +0100
+++ /var/tmp/diff_new_pack.g9bK5V/_new  2025-11-04 18:41:59.836518320 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           chezmoi
-Version:        2.66.1
+Version:        2.67.0
 Release:        0
 Summary:        A multi-host manager for dotfiles
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.g9bK5V/_old  2025-11-04 18:41:59.884520341 +0100
+++ /var/tmp/diff_new_pack.g9bK5V/_new  2025-11-04 18:41:59.892520679 +0100
@@ -2,7 +2,7 @@
   <service name="obs_scm" mode="manual">
     <param name="scm">git</param>
     <param name="url">https://github.com/twpayne/chezmoi.git</param>
-    <param name="revision">v2.66.1</param>
+    <param name="revision">v2.67.0</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
   </service>

++++++ chezmoi-2.66.1.obscpio -> chezmoi-2.67.0.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/.github/CODE_OF_CONDUCT.md 
new/chezmoi-2.67.0/.github/CODE_OF_CONDUCT.md
--- old/chezmoi-2.66.1/.github/CODE_OF_CONDUCT.md       2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/.github/CODE_OF_CONDUCT.md       2025-11-02 
19:55:46.000000000 +0100
@@ -4,16 +4,5 @@
 Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/) 
with
 the following additions for LLM (Large Language Model)-generated contributions:
 
-* You may use any tools you wish to generate content for chezmoi.
-
-* You must review the content for correctness and legal obligations before
-  contributing it.
-
-* If you contribute un-reviewed LLM-generated content with the admission that
-  you do not understand the content then you will receive a warning.
-
-* If you contribute un-reviewed LLM-generated content without any admission 
that
-  you used an LLM then you will immediately be banned without recourse.
-
-Example LLMs include, but are not limited to, ChatGPT, Claude, Gemini, GitHub
-Copilot, and Llama.
+* Any contribution of any LLM-generated content will be rejected and result in
+  an immediate ban for the contributor, without recourse.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/.github/workflows/installer.yml 
new/chezmoi-2.67.0/.github/workflows/installer.yml
--- old/chezmoi-2.66.1/.github/workflows/installer.yml  2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/.github/workflows/installer.yml  2025-11-02 
19:55:46.000000000 +0100
@@ -40,7 +40,7 @@
       contents: read
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
-    - uses: reviewdog/action-misspell@9daa94af4357dddb6fd3775de806bc0a8e98d3e4
+    - uses: reviewdog/action-misspell@d6429416b12b09b4e2768307d53bef58d172e962
       with:
         locale: US
   test-install-sh:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/.github/workflows/main.yml 
new/chezmoi-2.67.0/.github/workflows/main.yml
--- old/chezmoi-2.66.1/.github/workflows/main.yml       2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/.github/workflows/main.yml       2025-11-02 
19:55:46.000000000 +0100
@@ -18,12 +18,12 @@
   CHOCOLATEY_VERSION: 2.5.1 # https://github.com/chocolatey/choco/releases
   COSIGN_VERSION: 2.6.1 # https://github.com/sigstore/cosign/releases 
https://github.com/goreleaser/goreleaser/issues/6195
   GO_VERSION: 1.25.3 # https://go.dev/doc/devel/release
-  GOLANGCI_LINT_VERSION: 2.5.0 # 
https://github.com/golangci/golangci-lint/releases
-  GORELEASER_VERSION: 2.12.5 # 
https://github.com/goreleaser/goreleaser/releases
+  GOLANGCI_LINT_VERSION: 2.6.0 # 
https://github.com/golangci/golangci-lint/releases
+  GORELEASER_VERSION: 2.12.7 # 
https://github.com/goreleaser/goreleaser/releases
   PYTHON_VERSION: '3.10' # https://www.python.org/downloads/
   RAGE_VERSION: 0.11.1 # https://github.com/str4d/rage/releases
-  SYFT_VERSION: 1.34.2 # https://github.com/anchore/syft/releases
-  UV_VERSION: 0.9.4 # https://github.com/astral-sh/uv/releases
+  SYFT_VERSION: 1.36.0 # https://github.com/anchore/syft/releases
+  UV_VERSION: 0.9.7 # https://github.com/astral-sh/uv/releases
 jobs:
   changes:
     runs-on: ubuntu-22.04
@@ -76,7 +76,7 @@
       contents: read
     steps:
     - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
-    - uses: reviewdog/action-misspell@9daa94af4357dddb6fd3775de806bc0a8e98d3e4
+    - uses: reviewdog/action-misspell@d6429416b12b09b4e2768307d53bef58d172e962
       with:
         locale: US
   test-alpine:
@@ -192,31 +192,31 @@
         args: release --skip=sign --snapshot --timeout=1h
     - name: upload-artifact-chezmoi-darwin-amd64
       if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
-      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
         name: chezmoi-darwin-amd64
         path: dist/chezmoi-nocgo_darwin_amd64_v1/chezmoi
     - name: upload-artifact-chezmoi-darwin-arm64
       if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
-      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
         name: chezmoi-darwin-arm64
         path: dist/chezmoi-nocgo_darwin_arm64_v8.0/chezmoi
     - name: upload-artifact-chezmoi-linux-amd64
       if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
-      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
         name: chezmoi-linux-amd64
         path: dist/chezmoi-cgo-glibc_linux_amd64_v1/chezmoi
     - name: upload-artifact-chezmoi-linux-musl-amd64
       if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
-      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
         name: chezmoi-linux-amd64-musl
         path: dist/chezmoi-cgo-musl_linux_amd64_v1/chezmoi
     - name: upload-artifact-chezmoi-windows-amd64.exe
       if: github.event_name == 'push' || needs.changes.outputs.code == 'true'
-      uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
+      uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
       with:
         name: chezmoi-windows-amd64
         path: dist/chezmoi-nocgo_windows_amd64_v1/chezmoi.exe
@@ -280,7 +280,7 @@
       with:
         cache-prefix: website-go
         go-version: ${{ env.GO_VERSION }}
-    - uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24
+    - uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41
       with:
         enable-cache: true
         version: ${{ env.UV_VERSION }}
@@ -473,7 +473,7 @@
       with:
         cache-prefix: website-go
         go-version: ${{ env.GO_VERSION }}
-    - uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24
+    - uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41
       with:
         enable-cache: true
         version: ${{ env.UV_VERSION }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/.golangci.yml 
new/chezmoi-2.67.0/.golangci.yml
--- old/chezmoi-2.66.1/.golangci.yml    2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/.golangci.yml    2025-11-02 19:55:46.000000000 +0100
@@ -42,6 +42,7 @@
   - makezero
   - mirror
   - misspell
+  - modernize
   - nilerr
   - nilnesserr
   - nolintlint
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/developer-guide/contributing-changes.md
 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/developer-guide/contributing-changes.md
--- 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/developer-guide/contributing-changes.md
   2025-10-19 23:33:16.000000000 +0200
+++ 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/developer-guide/contributing-changes.md
   2025-11-02 19:55:46.000000000 +0100
@@ -35,15 +35,27 @@
 * The code passes [`golangci-lint`][golangci-lint]. You can ensure this by
   running `make lint`.
 
-* The commit messages follow the [conventional commits specification][commits].
-  chezmoi's release notes are generated directly from the commit messages. The
-  following criteria can be used to determine the commit type:
-
-      * Small changes, such as fixing a typo or correcting grammar: `chore`
-      * Bug fixes: `fix`
-      * Extending an existing feature, or adding a new feature: `feat`
-      * Adding to, or updating, the documentation: `docs`
-      * Anything not covered by the above: `chore`
+* The commit messages adhere to the [conventional commits 
specification][commits],
+  with the following additional requirements:
+
+      * The first character of the commit message is uppercase, e.g:
+
+          ```text
+          chore: Fix typo in test
+          ```
+
+        The purpose of this is to maintain consistency in chezmoi's release
+        notes, which are generated directly from the commit messages.
+
+      * The commits do not have scopes (e.g. `chore(scope): Message` is 
invalid).
+
+    The following criteria can be used to determine the commit type:
+
+      * `fix`: bug fixes in chezmoi code
+      * `feat`: extending an existing feature or adding a new feature
+      * `docs`: adding to or updating the documentation
+      * `chore`: small changes, such as fixing a typo, correcting grammar
+        (including in documentation), or anything not covered by the above
 
     Examples can be found in the [commit history][history].
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/developer-guide/index.md 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/developer-guide/index.md
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/developer-guide/index.md  
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/developer-guide/index.md  
2025-11-02 19:55:46.000000000 +0100
@@ -3,10 +3,8 @@
 !!! warning
 
     If you use an LLM (Large Language Model, like ChatGPT, Claude, Gemini,
-    GitHub Copilot, or Llama) to make a contribution then you must say so in
-    your contribution and you must carefully review your contribution for
-    correctness before sharing it. If you share un-reviewed LLM-generated
-    content then you will be immediately banned. See 
[`CODE_OF_CONDUCT.md`][coc]
+    GitHub Copilot, or Llama) to make any kind of contribution then you will
+    immediately be banned without recourse. See [`CODE_OF_CONDUCT.md`][coc]
     for more information.
 
 chezmoi is written in [Go][go] and development happens on [GitHub][github].
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/links/articles.md.yaml 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/links/articles.md.yaml
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/links/articles.md.yaml    
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/links/articles.md.yaml    
2025-11-02 19:55:46.000000000 +0100
@@ -605,3 +605,7 @@
   version: 2.65.2
   title: Testable Dotfiles Management With Chezmoi
   url: https://shunk031.me/post/testable-dotfiles-management-with-chezmoi/
+- date: '2025-11-02'
+  version: 2.66.1
+  title: Maintaining KDE dotfiles with Chezmoi Modify Manager
+  url: 
https://www.lorenzobettini.it/2025/11/maintaining-kde-dotfiles-with-chezmoi-modify-manager/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/links/related-software.md 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/links/related-software.md
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/links/related-software.md 
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/links/related-software.md 
2025-11-02 19:55:46.000000000 +0100
@@ -49,13 +49,17 @@
 
 chezmoi plugin for asdf version manager.
 
+### 
[`github.com/main-branch/chezroot`](https://github.com/main-branch/chezroot) { 
id="main-branch/chezroot" }
+
+A `sudo` wrapper for chezmoi to manage root-owned files across your entire 
filesystem.
+
 ### 
[`github.com/mass8326/zsh-chezmoi`](https://github.com/mass8326/zsh-chezmoi) { 
id="mass8326/zsh-chezmoi" }
 
 Add completion and aliases for chezmoi to make managing dotfiles easier to zsh.
 
 ### 
[`github.com/matmaer/chezmoi-mousse`](https://github.com/matmaer/chezmoi-mousse)
 { id="matmaer/chezmoi-mousse" }
 
-Visual interface in the terminal for the chezmoi dotfile managar, with a wink 
to the mouse.
+Visual interface in the terminal for the chezmoi dotfile manager, with a wink 
to the mouse.
 
 ### [Chezetc](https://silverrainz.me/chezetc/) { id="silverrainz.me/chezetc" }
 
@@ -63,7 +67,7 @@
 
 ### [`github.com/tcaxle/drapeau`](https://github.com/tcaxle/drapeau) { 
id="tcaxle/drapeau" }
 
-An add-on to synchronize your colorschemes across systems and allow easy
+An add-on to synchronize your color schemes across systems and allow easy
 colorscheme switching using chezmoi templates.
 
 ### 
[`github.com/VorpalBlade/chezmoi_modify_manager`](https://github.com/VorpalBlade/chezmoi_modify_manager)
 { id="vorpalblade/chezmoi_modify_manager" }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/reference/commands/add.md 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/reference/commands/add.md
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/reference/commands/add.md 
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/reference/commands/add.md 
2025-11-02 19:55:46.000000000 +0100
@@ -23,6 +23,13 @@
 
 Add files that should exist, irrespective of their contents.
 
+Sets the `create_` source state attribute on the added file.
+
+A file will be created with the given contents if the file does not exist.
+If the file already exists, then its contents will not be changed.
+This allows for managing files with an initial state but should not be changed
+by chezmoi afterwards.
+
 ### `--encrypt`
 
 > Configuration: `add.encrypt`
@@ -33,6 +40,12 @@
 
 Set the `exact` attribute on added directories.
 
+!!! warning
+
+    Directories with the `exact` attributes are statefully synced between 
target and source directories.
+    When running `re-add`, any files deleted from the `exact` target directory 
will be removed from the source directory.
+    Likewise, any files added to the `exact` target directory, will be added 
to the source directory
+
 ### `--follow`
 
 If the last part of a target is a symlink, add the target of the symlink
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/reference/commands/generate.md 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/reference/commands/generate.md
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/reference/commands/generate.md    
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/reference/commands/generate.md    
2025-11-02 19:55:46.000000000 +0100
@@ -12,6 +12,6 @@
 
 ```sh
 chezmoi generate install.sh > install.sh
-chezmoi git commit -m "$(chezmoi generate git-commit-message)"
+chezmoi git -- commit -m "$(chezmoi generate git-commit-message)"
 chezmoi generate install-init-shell.sh $GITHUB_USERNAME
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/assets/chezmoi.io/docs/user-guide/tools/merge.md 
new/chezmoi-2.67.0/assets/chezmoi.io/docs/user-guide/tools/merge.md
--- old/chezmoi-2.66.1/assets/chezmoi.io/docs/user-guide/tools/merge.md 
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/chezmoi.io/docs/user-guide/tools/merge.md 
2025-11-02 19:55:46.000000000 +0100
@@ -67,7 +67,7 @@
     command = "bash"
     args = [
         "-c",
-        "cp {{ .Target }} {{ .Target }}.base && code --new-window --wait 
--merge {{ .Destination }} {{ .Target }} {{ .Target }}.base {{ .Source }}",
+        "cp {{ .Target | quote }} {{ printf "%s.base" .Target | quote }} && 
code --new-window --wait --merge {{ .Destination | quote }} {{ .Target | quote 
}} {{ printf "%s.base" .Target | quote }} {{ .Source | quote }}",
     ]
     ```
 
@@ -78,7 +78,7 @@
       command: "bash"
       args:
       - "-c"
-      - "cp {{ .Target }} {{ .Target }}.base && code --new-window --wait 
--merge {{ .Destination }} {{ .Target }} {{ .Target }}.base {{ .Source }}"
+      - "cp {{ .Target | quote }} {{ printf \"%s.base\" .Target | quote }} && 
code --new-window --wait --merge {{ .Destination | quote }} {{ .Target | quote 
}} {{ printf \"%s.base\" .Target | quote }} {{ .Source | quote }}"
     ```
 
 [bcomp]: https://www.scootersoftware.com/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/assets/scripts/install-local-bin.sh 
new/chezmoi-2.67.0/assets/scripts/install-local-bin.sh
--- old/chezmoi-2.66.1/assets/scripts/install-local-bin.sh      2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/scripts/install-local-bin.sh      2025-11-02 
19:55:46.000000000 +0100
@@ -317,7 +317,7 @@
        checksums="${2}"
        basename="${target##*/}"
 
-       want="$(grep "${basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
+       want="$(grep "${basename}\$" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
        if [ -z "${want}" ]; then
                log_err "hash_sha256_verify unable to find checksum for 
${target} in ${checksums}"
                return 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/assets/scripts/install.sh 
new/chezmoi-2.67.0/assets/scripts/install.sh
--- old/chezmoi-2.66.1/assets/scripts/install.sh        2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/assets/scripts/install.sh        2025-11-02 
19:55:46.000000000 +0100
@@ -316,7 +316,7 @@
        checksums="${2}"
        basename="${target##*/}"
 
-       want="$(grep "${basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
+       want="$(grep "${basename}\$" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
        if [ -z "${want}" ]; then
                log_err "hash_sha256_verify unable to find checksum for 
${target} in ${checksums}"
                return 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/go.mod new/chezmoi-2.67.0/go.mod
--- old/chezmoi-2.66.1/go.mod   2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/go.mod   2025-11-02 19:55:46.000000000 +0100
@@ -29,9 +29,9 @@
        github.com/Masterminds/sprig/v3 v3.3.0
        github.com/Shopify/ejson v1.5.4
        github.com/alecthomas/assert/v2 v2.11.0
-       github.com/aws/aws-sdk-go-v2 v1.39.3
-       github.com/aws/aws-sdk-go-v2/config v1.31.13
-       github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.7
+       github.com/aws/aws-sdk-go-v2 v1.39.5
+       github.com/aws/aws-sdk-go-v2/config v1.31.16
+       github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.10
        github.com/bmatcuk/doublestar/v4 v4.9.1
        github.com/bradenhilton/mozillainstallhash v1.0.1
        github.com/charmbracelet/bubbles v0.20.0
@@ -48,7 +48,7 @@
        github.com/gopasspw/gopass v1.15.18
        github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
        github.com/itchyny/gojq v0.12.17
-       github.com/klauspost/compress v1.18.0
+       github.com/klauspost/compress v1.18.1
        github.com/mattn/go-runewidth v0.0.19
        github.com/mitchellh/copystructure v1.2.0
        github.com/muesli/combinator v0.3.0
@@ -100,16 +100,16 @@
        github.com/alecthomas/repr v0.5.2 // indirect
        github.com/andybalholm/brotli v1.2.0 // indirect
        github.com/atotto/clipboard v0.1.4 // indirect
-       github.com/aws/aws-sdk-go-v2/credentials v1.18.17 // indirect
-       github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.10 // indirect
-       github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.10 // indirect
-       github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.10 // indirect
+       github.com/aws/aws-sdk-go-v2/credentials v1.18.20 // indirect
+       github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12 // indirect
        github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
        github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 
// indirect
-       github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.10 // 
indirect
-       github.com/aws/aws-sdk-go-v2/service/sso v1.29.7 // indirect
-       github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.2 // indirect
-       github.com/aws/aws-sdk-go-v2/service/sts v1.38.7 // indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12 // 
indirect
+       github.com/aws/aws-sdk-go-v2/service/sso v1.30.0 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sts v1.39.0 // indirect
        github.com/aws/smithy-go v1.23.1 // indirect
        github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
        github.com/aymerick/douceur v0.2.0 // indirect
@@ -125,9 +125,10 @@
        github.com/charmbracelet/harmonica v0.2.0 // indirect
        github.com/charmbracelet/x/ansi v0.10.2 // indirect
        github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
-       github.com/charmbracelet/x/exp/slice v0.0.0-20251016201629-54e687c87a08 
// indirect
-       github.com/charmbracelet/x/term v0.2.1 // indirect
-       github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
+       github.com/charmbracelet/x/exp/slice v0.0.0-20251031172406-4542a189d0fb 
// indirect
+       github.com/charmbracelet/x/term v0.2.2 // indirect
+       github.com/clipperhouse/stringish v0.1.1 // indirect
+       github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
        github.com/cloudflare/circl v1.6.1 // indirect
        github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
        github.com/creack/pty/v2 v2.0.0-20231209135443-03db72c7b76c // indirect
@@ -216,7 +217,7 @@
        github.com/yuin/goldmark-emoji v1.0.6 // indirect
        go.yaml.in/yaml/v3 v3.0.4 // indirect
        go4.org v0.0.0-20230225012048-214862532bf5 // indirect
-       golang.org/x/exp v0.0.0-20251017212417-90e834f514db // indirect
+       golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
        golang.org/x/mod v0.29.0 // indirect
        golang.org/x/net v0.46.0 // indirect
        golang.org/x/tools v0.38.0 // indirect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/go.sum new/chezmoi-2.67.0/go.sum
--- old/chezmoi-2.66.1/go.sum   2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/go.sum   2025-11-02 19:55:46.000000000 +0100
@@ -91,32 +91,32 @@
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod 
h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/atotto/clipboard v0.1.4 
h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
 github.com/atotto/clipboard v0.1.4/go.mod 
h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
-github.com/aws/aws-sdk-go-v2 v1.39.3 
h1:h7xSsanJ4EQJXG5iuW4UqgP7qBopLpj84mpkNx3wPjM=
-github.com/aws/aws-sdk-go-v2 v1.39.3/go.mod 
h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=
-github.com/aws/aws-sdk-go-v2/config v1.31.13 
h1:wcqQB3B0PgRPUF5ZE/QL1JVOyB0mbPevHFoAMpemR9k=
-github.com/aws/aws-sdk-go-v2/config v1.31.13/go.mod 
h1:ySB5D5ybwqGbT6c3GszZ+u+3KvrlYCUQNo62+hkKOFk=
-github.com/aws/aws-sdk-go-v2/credentials v1.18.17 
h1:skpEwzN/+H8cdrrtT8y+rvWJGiWWv0DeNAe+4VTf+Vs=
-github.com/aws/aws-sdk-go-v2/credentials v1.18.17/go.mod 
h1:Ed+nXsaYa5uBINovJhcAWkALvXw2ZLk36opcuiSZfJM=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.10 
h1:UuGVOX48oP4vgQ36oiKmW9RuSeT8jlgQgBFQD+HUiHY=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.10/go.mod 
h1:vM/Ini41PzvudT4YkQyE/+WiQJiQ6jzeDyU8pQKwCac=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.10 
h1:mj/bdWleWEh81DtpdHKkw41IrS+r3uw1J/VQtbwYYp8=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.10/go.mod 
h1:7+oEMxAZWP8gZCyjcm9VicI0M61Sx4DJtcGfKYv2yKQ=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.10 
h1:wh+/mn57yhUrFtLIxyFPh2RgxgQz/u+Yrf7hiHGHqKY=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.10/go.mod 
h1:7zirD+ryp5gitJJ2m1BBux56ai8RIRDykXZrJSp540w=
+github.com/aws/aws-sdk-go-v2 v1.39.5 
h1:e/SXuia3rkFtapghJROrydtQpfQaaUgd1cUvyO1mp2w=
+github.com/aws/aws-sdk-go-v2 v1.39.5/go.mod 
h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=
+github.com/aws/aws-sdk-go-v2/config v1.31.16 
h1:E4Tz+tJiPc7kGnXwIfCyUj6xHJNpENlY11oKpRTgsjc=
+github.com/aws/aws-sdk-go-v2/config v1.31.16/go.mod 
h1:2S9hBElpCyGMifv14WxQ7EfPumgoeCPZUpuPX8VtW34=
+github.com/aws/aws-sdk-go-v2/credentials v1.18.20 
h1:KFndAnHd9NUuzikHjQ8D5CfFVO+bgELkmcGY8yAw98Q=
+github.com/aws/aws-sdk-go-v2/credentials v1.18.20/go.mod 
h1:9mCi28a+fmBHSQ0UM79omkz6JtN+PEsvLrnG36uoUv0=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12 
h1:VO3FIM2TDbm0kqp6sFNR0PbioXJb/HzCDW6NtIZpIWE=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12/go.mod 
h1:6C39gB8kg82tx3r72muZSrNhHia9rjGkX7ORaS2GKNE=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12 
h1:p/9flfXdoAnwJnuW9xHEAFY22R3A6skYkW19JFF9F+8=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12/go.mod 
h1:ZTLHakoVCTtW8AaLGSwJ3LXqHD9uQKnOcv1TrpO6u2k=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12 
h1:2lTWFvRcnWFFLzHWmtddu5MTchc5Oj2OOey++99tPZ0=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12/go.mod 
h1:hI92pK+ho8HVcWMHKHrK3Uml4pfG7wvL86FzO0LVtQQ=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 
h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod 
h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 
h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod 
h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.10 
h1:DRND0dkCKtJzCj4Xl4OpVbXZgfttY5q712H9Zj7qc/0=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.10/go.mod 
h1:tGGNmJKOTernmR2+VJ0fCzQRurcPZj9ut60Zu5Fi6us=
-github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.7 
h1:ac9qk31MWmUlUci1tthz0iREvkjFktEeGaDF1fAgeCU=
-github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.7/go.mod 
h1:A3WcpfEY2lhQvpnS6SJbMfljJuskxIKIVDcuYbIbXeE=
-github.com/aws/aws-sdk-go-v2/service/sso v1.29.7 
h1:fspVFg6qMx0svs40YgRmE7LZXh9VRZvTT35PfdQR6FM=
-github.com/aws/aws-sdk-go-v2/service/sso v1.29.7/go.mod 
h1:BQTKL3uMECaLaUV3Zc2L4Qybv8C6BIXjuu1dOPyxTQs=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.2 
h1:scVnW+NLXasGOhy7HhkdT9AGb6kjgW7fJ5xYkUaqHs0=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.2/go.mod 
h1:FRNCY3zTEWZXBKm2h5UBUPvCVDOecTad9KhynDyGBc0=
-github.com/aws/aws-sdk-go-v2/service/sts v1.38.7 
h1:VEO5dqFkMsl8QZ2yHsFDJAIZLAkEbaYDB+xdKi0Feic=
-github.com/aws/aws-sdk-go-v2/service/sts v1.38.7/go.mod 
h1:L1xxV3zAdB+qVrVW/pBIrIAnHFWHo6FBbFe4xOGsG/o=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12 
h1:MM8imH7NZ0ovIVX7D2RxfMDv7Jt9OiUXkcQ+GqywA7M=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12/go.mod 
h1:gf4OGwdNkbEsb7elw2Sy76odfhwNktWII3WgvQgQQ6w=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.10 
h1:S5Mw93I9uFjXnHvkZ19O3Zj0UM5k4v3pYrDZxXCbqUg=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.10/go.mod 
h1:wW/JqWY6yVr88XZJq5wX22l8XNkDdhw+8eDgkN51Rlc=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.0 
h1:xHXvxst78wBpJFgDW07xllOx0IAzbryrSdM4nMVQ4Dw=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.0/go.mod 
h1:/e8m+AO6HNPPqMyfKRtzZ9+mBF5/x1Wk8QiDva4m07I=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4 
h1:tBw2Qhf0kj4ZwtsVpDiVRU3zKLvjvjgIjHMKirxXg8M=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4/go.mod 
h1:Deq4B7sRM6Awq/xyOBlxBdgW8/Z926KYNNaGMW2lrkA=
+github.com/aws/aws-sdk-go-v2/service/sts v1.39.0 
h1:C+BRMnasSYFcgDw8o9H5hzehKzXyAb9GY5v/8bP9DUY=
+github.com/aws/aws-sdk-go-v2/service/sts v1.39.0/go.mod 
h1:4EjU+4mIx6+JqKQkruye+CaigV7alL3thVPfDd9VlMs=
 github.com/aws/smithy-go v1.23.1 
h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M=
 github.com/aws/smithy-go v1.23.1/go.mod 
h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
 github.com/aymanbagabas/go-osc52/v2 v2.0.1 
h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
@@ -171,10 +171,10 @@
 github.com/charmbracelet/x/cellbuf v0.0.13/go.mod 
h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b 
h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
 github.com/charmbracelet/x/exp/golden 
v0.0.0-20240815200342-61de596daa2b/go.mod 
h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
-github.com/charmbracelet/x/exp/slice v0.0.0-20251016201629-54e687c87a08 
h1:QgWxcPNK0kuOBW6/wQjRxvlnUou6nX4JOBcl3tZpEKk=
-github.com/charmbracelet/x/exp/slice v0.0.0-20251016201629-54e687c87a08/go.mod 
h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
-github.com/charmbracelet/x/term v0.2.1 
h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
-github.com/charmbracelet/x/term v0.2.1/go.mod 
h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
+github.com/charmbracelet/x/exp/slice v0.0.0-20251031172406-4542a189d0fb 
h1:r8GKL5AcwENTjZfNhSFv2E5qF4t8KshHPdN2qkPe9F4=
+github.com/charmbracelet/x/exp/slice v0.0.0-20251031172406-4542a189d0fb/go.mod 
h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA=
+github.com/charmbracelet/x/term v0.2.2 
h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
+github.com/charmbracelet/x/term v0.2.2/go.mod 
h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
 github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
 github.com/chzyer/logex v1.1.10/go.mod 
h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e 
h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
@@ -183,8 +183,10 @@
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod 
h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 github.com/client9/misspell v0.3.4 
h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
 github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/clipperhouse/uax29/v2 v2.2.0 
h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
-github.com/clipperhouse/uax29/v2 v2.2.0/go.mod 
h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
+github.com/clipperhouse/stringish v0.1.1 
h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
+github.com/clipperhouse/stringish v0.1.1/go.mod 
h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
+github.com/clipperhouse/uax29/v2 v2.3.0 
h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
+github.com/clipperhouse/uax29/v2 v2.3.0/go.mod 
h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
 github.com/cloudflare/circl v1.6.1 
h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
 github.com/cloudflare/circl v1.6.1/go.mod 
h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
 github.com/coreos/go-semver v0.3.1 
h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
@@ -416,8 +418,8 @@
 github.com/kjk/lzmadec v0.0.0-20210713164611-19ac3ee91a71 
h1:TYp9Fj0apeZMWentXRaFM6B0ixdFefrlgY8n8XYEz1s=
 github.com/kjk/lzmadec v0.0.0-20210713164611-19ac3ee91a71/go.mod 
h1:2zRkQCuw/eK6cqkYAeNqyBU7JKa2Gcq40BZ9GSJbmfE=
 github.com/klauspost/compress v1.4.1/go.mod 
h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.18.0 
h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
-github.com/klauspost/compress v1.18.0/go.mod 
h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/klauspost/compress v1.18.1 
h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
+github.com/klauspost/compress v1.18.1/go.mod 
h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
 github.com/klauspost/cpuid v1.2.0 
h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
 github.com/klauspost/cpuid v1.2.0/go.mod 
h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/klauspost/cpuid/v2 v2.3.0 
h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
@@ -692,8 +694,8 @@
 golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod 
h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod 
h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod 
h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20251017212417-90e834f514db 
h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw=
-golang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod 
h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
+golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 
h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
+golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod 
h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod 
h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b 
h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod 
h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/chezmoi/abspath.go 
new/chezmoi-2.67.0/internal/chezmoi/abspath.go
--- old/chezmoi-2.66.1/internal/chezmoi/abspath.go      2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/abspath.go      2025-11-02 
19:55:46.000000000 +0100
@@ -165,7 +165,7 @@
 // from a string.
 func StringToAbsPathHookFunc() mapstructure.DecodeHookFunc {
        return func(from, to reflect.Type, data any) (any, error) {
-               if to != reflect.TypeOf(EmptyAbsPath) {
+               if to != reflect.TypeFor[AbsPath]() {
                        return data, nil
                }
                s, ok := data.(string)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/chezmoi/chezmoi.go 
new/chezmoi-2.67.0/internal/chezmoi/chezmoi.go
--- old/chezmoi-2.66.1/internal/chezmoi/chezmoi.go      2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/chezmoi.go      2025-11-02 
19:55:46.000000000 +0100
@@ -120,6 +120,20 @@
        "chezmoistate.boltdb",
 )
 
+// ignoredHostnameSuffixes is a list of suffixes that are ignored when
+// determining the hostname from /etc/hosts. See
+// https://en.wikipedia.org/wiki/Special-use_domain_name.
+var ignoredHostnameSuffixes = []string{
+       ".alt",
+       ".example",
+       ".invalid",
+       ".internal",
+       ".local",
+       ".localhost",
+       ".onion",
+       ".test",
+}
+
 var FileModeTypeNames = map[fs.FileMode]string{
        0:                 "file",
        fs.ModeDir:        "dir",
@@ -283,34 +297,26 @@
        if err != nil {
                return "", err
        }
+LINE:
        for line := range bytes.Lines(contents) {
                line, _, _ = bytes.Cut(bytes.TrimSpace(line), []byte{'#'})
                fields := whitespaceRx.Split(string(line), -1)
                if len(fields) < 2 {
                        continue
                }
-               if !net.ParseIP(fields[0]).IsLoopback() {
-                       continue
-               }
-               hostname, domainname, found := strings.Cut(fields[1], ".")
-               if !found {
-                       continue
-               }
-               if hostname == "localhost" {
-                       continue
-               }
-               if domainname == "localdomain" {
+               ipAddress, canonicalHostname := fields[0], fields[1]
+               if !net.ParseIP(ipAddress).IsLoopback() {
                        continue
                }
-               // Docker Desktop breaks /etc/hosts. Filter out all 
docker.internal
-               // domain names. See 
https://github.com/twpayne/chezmoi/issues/3095.
-               if domainname == "docker.internal" {
+               if hostname, _, found := strings.Cut(canonicalHostname, "."); 
!found || hostname == "localhost" {
                        continue
                }
-               if runtime.GOOS == "darwin" && domainname == "local" {
-                       continue
+               for _, ignoredHostnameSuffix := range ignoredHostnameSuffixes {
+                       if strings.HasSuffix(canonicalHostname, 
ignoredHostnameSuffix) {
+                               continue LINE
+                       }
                }
-               return fields[1], nil
+               return canonicalHostname, nil
        }
        return "", nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/chezmoi/chezmoi_test.go 
new/chezmoi-2.67.0/internal/chezmoi/chezmoi_test.go
--- old/chezmoi-2.66.1/internal/chezmoi/chezmoi_test.go 2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/chezmoi_test.go 2025-11-02 
19:55:46.000000000 +0100
@@ -58,7 +58,9 @@
                        root: map[string]any{
                                "/etc/hosts": chezmoitest.JoinLines(
                                        `127.0.0.1 localhost.localdomain`,
-                                       `127.0.0.2 host.example.com host`,
+                                       `127.0.0.2 service.local`,
+                                       `127.0.0.4 multi.part.domain.example`,
+                                       `127.0.0.4 host.example.com host`,
                                ),
                        },
                        f:        etcHostsFQDNHostname,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/chezmoi/entrytypeset.go 
new/chezmoi-2.67.0/internal/chezmoi/entrytypeset.go
--- old/chezmoi-2.66.1/internal/chezmoi/entrytypeset.go 2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/entrytypeset.go 2025-11-02 
19:55:46.000000000 +0100
@@ -347,7 +347,7 @@
 // EntryTypeSet from a []string.
 func StringSliceToEntryTypeSetHookFunc() mapstructure.DecodeHookFunc {
        return func(from, to reflect.Type, data any) (any, error) {
-               if to != reflect.TypeOf(EntryTypeSet{}) {
+               if to != reflect.TypeFor[EntryTypeSet]() {
                        return data, nil
                }
                elemsAny, ok := data.([]any)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/chezmoi/externaldiffsystem.go 
new/chezmoi-2.67.0/internal/chezmoi/externaldiffsystem.go
--- old/chezmoi-2.66.1/internal/chezmoi/externaldiffsystem.go   2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/externaldiffsystem.go   2025-11-02 
19:55:46.000000000 +0100
@@ -8,8 +8,6 @@
        "os"
        "os/exec"
        "strconv"
-       "strings"
-       "text/template"
        "time"
 
        vfs "github.com/twpayne/go-vfs/v5"
@@ -19,24 +17,26 @@
 
 // An ExternalDiffSystem is a DiffSystem that uses an external diff tool.
 type ExternalDiffSystem struct {
-       system         System
-       command        string
-       args           []string
-       destDirAbsPath AbsPath
-       tempDirAbsPath AbsPath
-       filter         *EntryTypeFilter
-       pagerCmdFunc   func() (*exec.Cmd, error)
-       reverse        bool
-       scriptContents bool
-       textConvFunc   TextConvFunc
+       system          System
+       command         string
+       args            []string
+       destDirAbsPath  AbsPath
+       tempDirAbsPath  AbsPath
+       filter          *EntryTypeFilter
+       pagerCmdFunc    func() (*exec.Cmd, error)
+       reverse         bool
+       scriptContents  bool
+       templateOptions TemplateOptions
+       textConvFunc    TextConvFunc
 }
 
 // ExternalDiffSystemOptions are options for NewExternalDiffSystem.
 type ExternalDiffSystemOptions struct {
-       Filter         *EntryTypeFilter
-       Reverse        bool
-       ScriptContents bool
-       TextConvFunc   TextConvFunc
+       Filter          *EntryTypeFilter
+       Reverse         bool
+       ScriptContents  bool
+       TextConvFunc    TextConvFunc
+       TemplateOptions TemplateOptions
 }
 
 // NewExternalDiffSystem creates a new ExternalDiffSystem.
@@ -49,15 +49,16 @@
        options *ExternalDiffSystemOptions,
 ) *ExternalDiffSystem {
        return &ExternalDiffSystem{
-               system:         system,
-               command:        command,
-               args:           args,
-               destDirAbsPath: destDirAbsPath,
-               filter:         options.Filter,
-               pagerCmdFunc:   pagerCmdFunc,
-               reverse:        options.Reverse,
-               scriptContents: options.ScriptContents,
-               textConvFunc:   options.TextConvFunc,
+               system:          system,
+               command:         command,
+               args:            args,
+               destDirAbsPath:  destDirAbsPath,
+               filter:          options.Filter,
+               pagerCmdFunc:    pagerCmdFunc,
+               reverse:         options.Reverse,
+               scriptContents:  options.ScriptContents,
+               templateOptions: options.TemplateOptions,
+               textConvFunc:    options.TextConvFunc,
        }
 }
 
@@ -213,19 +214,19 @@
        // to the original arg.
        anyTemplateArgs := false
        for i, arg := range s.args {
-               tmpl, err := template.New("diff.args[" + strconv.Itoa(i) + 
"]").Parse(arg)
+               tmpl, err := ParseTemplate("diff.args["+strconv.Itoa(i)+"]", 
[]byte(arg), s.templateOptions)
                if err != nil {
                        return err
                }
 
-               builder := strings.Builder{}
-               if err := tmpl.Execute(&builder, templateData); err != nil {
+               newArg, err := tmpl.ExecuteString(templateData)
+               if err != nil {
                        return err
                }
-               args = append(args, builder.String())
+               args = append(args, newArg)
 
                // Detect template arguments.
-               if arg != builder.String() {
+               if arg != newArg {
                        anyTemplateArgs = true
                }
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/chezmoi/template.go 
new/chezmoi-2.67.0/internal/chezmoi/template.go
--- old/chezmoi-2.66.1/internal/chezmoi/template.go     2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/chezmoi/template.go     2025-11-02 
19:55:46.000000000 +0100
@@ -119,6 +119,15 @@
        return result, nil
 }
 
+// ExecuteString executes t with s.
+func (t *Template) ExecuteString(data any) (string, error) {
+       resultBytes, err := t.Execute(data)
+       if err != nil {
+               return "", err
+       }
+       return string(resultBytes), err
+}
+
 // parseAndRemoveDirectives updates o by parsing all template directives in 
data
 // and returns data with the lines containing directives removed. The lines are
 // removed so that any delimiters do not break template parsing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/autobool.go 
new/chezmoi-2.67.0/internal/cmd/autobool.go
--- old/chezmoi-2.66.1/internal/cmd/autobool.go 2025-10-19 23:33:16.000000000 
+0200
+++ new/chezmoi-2.67.0/internal/cmd/autobool.go 2025-11-02 19:55:46.000000000 
+0100
@@ -116,7 +116,7 @@
 // from a bool or string.
 func StringOrBoolToAutoBoolHookFunc() mapstructure.DecodeHookFunc {
        return func(from, to reflect.Type, data any) (any, error) {
-               if to != reflect.TypeOf(autoBool{}) {
+               if to != reflect.TypeFor[autoBool]() {
                        return data, nil
                }
                var b autoBool
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/choiceflag.go 
new/chezmoi-2.67.0/internal/cmd/choiceflag.go
--- old/chezmoi-2.66.1/internal/cmd/choiceflag.go       2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmd/choiceflag.go       2025-11-02 
19:55:46.000000000 +0100
@@ -124,7 +124,7 @@
 // So, we have to return a choiceFlag that allows all values.
 func StringToChoiceFlagHookFunc() mapstructure.DecodeHookFunc {
        return func(from, to reflect.Type, data any) (any, error) {
-               if to != reflect.TypeOf(choiceFlag{}) {
+               if to != reflect.TypeFor[choiceFlag]() {
                        return data, nil
                }
                var cf choiceFlag
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/config.go 
new/chezmoi-2.67.0/internal/cmd/config.go
--- old/chezmoi-2.66.1/internal/cmd/config.go   2025-10-19 23:33:16.000000000 
+0200
+++ new/chezmoi-2.67.0/internal/cmd/config.go   2025-11-02 19:55:46.000000000 
+0100
@@ -1976,7 +1976,11 @@
                Filter:         
chezmoi.NewEntryTypeFilter(c.Diff.include.Bits(), c.Diff.Exclude.Bits()),
                Reverse:        c.Diff.Reverse,
                ScriptContents: c.Diff.ScriptContents,
-               TextConvFunc:   c.TextConv.convert,
+               TemplateOptions: chezmoi.TemplateOptions{
+                       Funcs:   c.templateFuncs,
+                       Options: c.Template.Options,
+               },
+               TextConvFunc: c.TextConv.convert,
        }
        return chezmoi.NewExternalDiffSystem(s, c.Diff.Command, c.Diff.Args, 
c.DestDirAbsPath, c.getDiffPagerCmd, options)
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/helps.gen.go 
new/chezmoi-2.67.0/internal/cmd/helps.gen.go
--- old/chezmoi-2.66.1/internal/cmd/helps.gen.go        2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmd/helps.gen.go        2025-11-02 
19:55:46.000000000 +0100
@@ -438,7 +438,7 @@
                        "                         | init, and executes your 
shell",
                example: "" +
                        "  chezmoi generate install.sh > install.sh\n" +
-                       "  chezmoi git commit -m \"$(chezmoi generate 
git-commit-message)\"\n" +
+                       "  chezmoi git -- commit -m \"$(chezmoi generate 
git-commit-message)\"\n" +
                        "  chezmoi generate install-init-shell.sh 
$GITHUB_USERNAME",
        },
        "git": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/mergecmd.go 
new/chezmoi-2.67.0/internal/cmd/mergecmd.go
--- old/chezmoi-2.66.1/internal/cmd/mergecmd.go 2025-10-19 23:33:16.000000000 
+0200
+++ new/chezmoi-2.67.0/internal/cmd/mergecmd.go 2025-11-02 19:55:46.000000000 
+0100
@@ -4,8 +4,6 @@
        "fmt"
        "os"
        "strconv"
-       "strings"
-       "text/template"
 
        "github.com/spf13/cobra"
 
@@ -146,19 +144,21 @@
        // not equal to the original arg.
        anyTemplateArgs := false
        for i, arg := range c.Merge.Args {
-               var tmpl *template.Template
-               if tmpl, err = template.New("merge.args[" + strconv.Itoa(i) + 
"]").Parse(arg); err != nil {
+               tmpl, err := 
chezmoi.ParseTemplate("merge.args["+strconv.Itoa(i)+"]", []byte(arg), 
chezmoi.TemplateOptions{
+                       Funcs:   c.templateFuncs,
+                       Options: c.Template.Options,
+               })
+               if err != nil {
                        return err
                }
-
-               builder := strings.Builder{}
-               if err := tmpl.Execute(&builder, templateData); err != nil {
+               newArg, err := tmpl.ExecuteString(templateData)
+               if err != nil {
                        return err
                }
-               args = append(args, builder.String())
+               args = append(args, newArg)
 
                // Detect template arguments.
-               if arg != builder.String() {
+               if newArg != arg {
                        anyTemplateArgs = true
                }
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/readdcmd.go 
new/chezmoi-2.67.0/internal/cmd/readdcmd.go
--- old/chezmoi-2.66.1/internal/cmd/readdcmd.go 2025-10-19 23:33:16.000000000 
+0200
+++ new/chezmoi-2.67.0/internal/cmd/readdcmd.go 2025-11-02 19:55:46.000000000 
+0100
@@ -84,6 +84,9 @@
        }
        slices.SortFunc(targetRelPaths, chezmoi.CompareRelPaths)
 
+       // Track which files were already processed to avoid double-processing 
with exact directories
+       processedFiles := make(map[chezmoi.RelPath]bool)
+
 TARGET_REL_PATH:
        for _, targetRelPath := range targetRelPaths {
                sourceStateFile, ok := 
sourceStateEntries[targetRelPath].(*chezmoi.SourceStateFile)
@@ -198,6 +201,150 @@
                }); err != nil {
                        return err
                }
+               // Mark this file as processed
+               processedFiles[targetRelPath] = true
+       }
+
+       // Process exact directories - add new files and remove deleted files
+       return c.processExactDirs(sourceState, sourceStateEntries, 
processedFiles)
+}
+
+// processExactDirs handles exact directory synchronization during re-add.
+// It adds new files found in exact target directories and removes files from
+// source that no longer exist in exact target directories.
+// processedFiles contains files that were already re-added in the file loop,
+// outside of the exact directory logic, to avoid double-processing them.
+func (c *Config) processExactDirs(
+       sourceState *chezmoi.SourceState,
+       sourceStateEntries map[chezmoi.RelPath]chezmoi.SourceStateEntry,
+       processedFiles map[chezmoi.RelPath]bool,
+) error {
+       // Collect all exact directories from source state that are in scope
+       // An exact directory is in scope if:
+       // 1. It's directly in sourceStateEntries (was explicitly or implicitly 
targeted)
+       // 2. Any of its children are in sourceStateEntries (parent dir needs 
sync)
+       exactDirs := make(map[chezmoi.RelPath]*chezmoi.SourceStateDir)
+
+       // First, collect exact directories that are directly in the entries
+       for targetRelPath, entry := range sourceStateEntries {
+               if sourceStateDir, ok := entry.(*chezmoi.SourceStateDir); ok && 
sourceStateDir.Attr.Exact {
+                       exactDirs[targetRelPath] = sourceStateDir
+               }
+       }
+
+       // Then, collect parent exact directories for any entries
+       for targetRelPath := range sourceStateEntries {
+               // Walk up the path to find parent exact directories
+               for parentPath := targetRelPath.Dir(); parentPath != 
chezmoi.DotRelPath; parentPath = parentPath.Dir() {
+                       // Check if this parent is an exact directory in source 
state
+                       parentEntry := sourceState.Get(parentPath)
+                       if sourceStateDir, ok := 
parentEntry.(*chezmoi.SourceStateDir); ok && sourceStateDir.Attr.Exact {
+                               // Only add if not already present
+                               if _, exists := exactDirs[parentPath]; !exists {
+                                       exactDirs[parentPath] = sourceStateDir
+                               }
+                       }
+               }
+       }
+
+       // Process each exact directory
+       for targetRelPath := range exactDirs {
+               targetDirAbsPath := c.DestDirAbsPath.Join(targetRelPath)
+
+               // Read the target directory contents
+               dirEntries, err := c.destSystem.ReadDir(targetDirAbsPath)
+               if err != nil {
+                       // If directory doesn't exist in target, skip it
+                       continue
+               }
+
+               // Build sets of files in source and target
+               sourceFiles := make(map[string]chezmoi.SourceStateEntry)
+               targetFiles := make(map[string]fs.DirEntry)
+
+               // Collect files from source state that are in this exact 
directory
+               // Only consider actual files, not removes or other entry types
+               for entryRelPath, entry := range sourceStateEntries {
+                       // Check if this entry is a direct child of the exact 
directory
+                       if entryRelPath.Dir() == targetRelPath {
+                               // Only count actual files in source, not 
remove entries
+                               if _, ok := entry.(*chezmoi.SourceStateFile); 
ok {
+                                       sourceFiles[entryRelPath.Base()] = entry
+                               }
+                       }
+               }
+
+               // Collect files from target directory
+               for _, dirEntry := range dirEntries {
+                       name := dirEntry.Name()
+                       if name == "." || name == ".." {
+                               continue
+                       }
+                       targetFiles[name] = dirEntry
+               }
+
+               // Find new files (in target but not in source) and add them
+               destAbsPathInfos := make(map[chezmoi.AbsPath]fs.FileInfo)
+               for name, dirEntry := range targetFiles {
+                       entryRelPath := targetRelPath.JoinString(name)
+
+                       // Skip files that were already processed in the file 
re-add loop
+                       if processedFiles[entryRelPath] {
+                               continue
+                       }
+
+                       if _, inSource := sourceFiles[name]; !inSource {
+                               // Check if ignored
+                               if sourceState.Ignore(entryRelPath) {
+                                       continue
+                               }
+
+                               // Skip subdirectories that are themselves 
exact directories
+                               // They will be processed separately in their 
own exact directory processing
+                               if dirEntry.IsDir() {
+                                       childEntry := 
sourceState.Get(entryRelPath)
+                                       if childDir, ok := 
childEntry.(*chezmoi.SourceStateDir); ok && childDir.Attr.Exact {
+                                               continue
+                                       }
+                               }
+
+                               // This is a new file - add it
+                               // Get full FileInfo (DirEntry only has partial 
info)
+                               destAbsPath := targetDirAbsPath.JoinString(name)
+                               fileInfo, err := dirEntry.Info()
+                               if err != nil {
+                                       return err
+                               }
+                               destAbsPathInfos[destAbsPath] = fileInfo
+                       }
+               }
+
+               // Add new files if any were found
+               if len(destAbsPathInfos) > 0 {
+                       if err := sourceState.Add(c.sourceSystem, 
c.persistentState, c.destSystem, destAbsPathInfos, &chezmoi.AddOptions{
+                               Filter:     c.reAdd.filter,
+                               PreAddFunc: c.defaultPreAddFunc,
+                       }); err != nil {
+                               return err
+                       }
+               }
+
+               // Find deleted files (in source but not in target) and remove 
them
+               for name, sourceEntry := range sourceFiles {
+                       if _, inTarget := targetFiles[name]; !inTarget {
+                               // Check if ignored
+                               entryRelPath := targetRelPath.JoinString(name)
+                               if sourceState.Ignore(entryRelPath) {
+                                       continue
+                               }
+
+                               // This file was deleted from target - remove 
it from source
+                               sourceAbsPath := 
c.SourceDirAbsPath.Join(sourceEntry.SourceRelPath().RelPath())
+                               if err := 
c.sourceSystem.RemoveAll(sourceAbsPath); err != nil {
+                                       return err
+                               }
+                       }
+               }
        }
 
        return nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/templatefuncs.go 
new/chezmoi-2.67.0/internal/cmd/templatefuncs.go
--- old/chezmoi-2.66.1/internal/cmd/templatefuncs.go    2025-10-19 
23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmd/templatefuncs.go    2025-11-02 
19:55:46.000000000 +0100
@@ -173,7 +173,9 @@
 }
 
 func (c *Config) fromIniTemplateFunc(s string) map[string]any {
-       return iniFileToMap(mustValue(ini.Load([]byte(s))))
+       return iniFileToMap(mustValue(ini.LoadSources(ini.LoadOptions{
+               UnescapeValueDoubleQuotes: true,
+       }, []byte(s))))
 }
 
 // fromJsonTemplateFunc parses s as JSON and returns the result. In contrast to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/cmd/testdata/scripts/applyexact.txtar 
new/chezmoi-2.67.0/internal/cmd/testdata/scripts/applyexact.txtar
--- old/chezmoi-2.66.1/internal/cmd/testdata/scripts/applyexact.txtar   
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmd/testdata/scripts/applyexact.txtar   
2025-11-02 19:55:46.000000000 +0100
@@ -10,6 +10,13 @@
 ! exists $HOME/.dir/file2
 ! exists $HOME/.dir/subdir/file
 
+# test that chezmoi apply creates entries in exact directories
+cp golden/file3 $CHEZMOISOURCEDIR/exact_dot_dir
+exec chezmoi apply --force
+cmp $HOME/.dir/file3 golden/file3
+
+-- golden/file3 --
+# contents of .dir/file2
 -- home/user/.dir/file1 --
 # contents of .dir/file1
 -- home/user/.dir/file2 --
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/cmd/testdata/scripts/issue4727.txtar 
new/chezmoi-2.67.0/internal/cmd/testdata/scripts/issue4727.txtar
--- old/chezmoi-2.66.1/internal/cmd/testdata/scripts/issue4727.txtar    
1970-01-01 01:00:00.000000000 +0100
+++ new/chezmoi-2.67.0/internal/cmd/testdata/scripts/issue4727.txtar    
2025-11-02 19:55:46.000000000 +0100
@@ -0,0 +1,6 @@
+# test that fromIni | toIni does not mangle strings
+exec chezmoi execute-template '{{ "a = \"\\\"\"" | fromIni | toIni | fromIni | 
toIni }}'
+cmp stdout golden/stdout
+
+-- golden/stdout --
+a = "\""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/cmd/testdata/scripts/re-add.txtar 
new/chezmoi-2.67.0/internal/cmd/testdata/scripts/re-add.txtar
--- old/chezmoi-2.66.1/internal/cmd/testdata/scripts/re-add.txtar       
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmd/testdata/scripts/re-add.txtar       
2025-11-02 19:55:46.000000000 +0100
@@ -22,10 +22,12 @@
 grep -count=2 '# edited' $CHEZMOISOURCEDIR/dot_dir/file
 grep -count=1 '# edited' $CHEZMOISOURCEDIR/dot_dir/exact_subdir/file
 
-# test that chezmoi re-add --recursive=false does not recurse into 
subdirectories
+# test that chezmoi re-add --recursive=false does not recurse into 
subdirectories AND still syncs exact directories
+# Even with --recursive=false, exact directory sync happens because subdir is 
exact
 exec chezmoi re-add --recursive=false ~/.dir/subdir
-grep -count=1 '# edited' $CHEZMOISOURCEDIR/dot_dir/exact_subdir/file
+grep -count=2 '# edited' $CHEZMOISOURCEDIR/dot_dir/exact_subdir/file
 
 # test that chezmoi re-add is recursive by default
+edit $HOME/.dir/subdir/file
 exec chezmoi re-add ~/.dir/subdir
-grep -count=2 '# edited' $CHEZMOISOURCEDIR/dot_dir/exact_subdir/file
+grep -count=3 '# edited' $CHEZMOISOURCEDIR/dot_dir/exact_subdir/file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/cmd/testdata/scripts/readd-exact.txtar 
new/chezmoi-2.67.0/internal/cmd/testdata/scripts/readd-exact.txtar
--- old/chezmoi-2.66.1/internal/cmd/testdata/scripts/readd-exact.txtar  
1970-01-01 01:00:00.000000000 +0100
+++ new/chezmoi-2.67.0/internal/cmd/testdata/scripts/readd-exact.txtar  
2025-11-02 19:55:46.000000000 +0100
@@ -0,0 +1,95 @@
+# test that chezmoi re-add adds new files in exact_ directories
+exec chezmoi add --exact $HOME${/}test-dir
+exists $CHEZMOISOURCEDIR/exact_test-dir/test1
+cmp $CHEZMOISOURCEDIR/exact_test-dir/test1 golden/test1
+
+# verify no diff after initial add
+exec chezmoi diff
+! stdout .
+
+# add a new file to the exact directory in target
+cp golden/test2 $HOME/test-dir/test2
+exec chezmoi re-add
+exists $CHEZMOISOURCEDIR/exact_test-dir/test2
+cmp $CHEZMOISOURCEDIR/exact_test-dir/test2 golden/test2
+
+# verify no diff after adding new file
+exec chezmoi diff
+! stdout .
+
+# test that chezmoi re-add removes deleted files from exact_ directories
+rm $HOME/test-dir/test1
+exec chezmoi re-add
+! exists $CHEZMOISOURCEDIR/exact_test-dir/test1
+
+# verify no diff after removing file
+exec chezmoi diff
+! stdout .
+
+# test that chezmoi re-add with explicit exact directory target works
+cp golden/test3 $HOME/test-dir/test3
+exec chezmoi re-add $HOME/test-dir
+exists $CHEZMOISOURCEDIR/exact_test-dir/test3
+cmp $CHEZMOISOURCEDIR/exact_test-dir/test3 golden/test3
+
+# verify no diff after adding file with explicit target
+exec chezmoi diff
+! stdout .
+
+# test nested exact directory with --recursive=false
+exec chezmoi add $HOME/outer-dir
+exec chezmoi add --exact $HOME/outer-dir/exact-inner
+exists $CHEZMOISOURCEDIR/outer-dir/exact_exact-inner/inner1
+
+# add a new file to the nested exact directory in target
+cp golden/inner2 $HOME/outer-dir/exact-inner/inner2
+
+# re-add with --recursive=false should NOT process nested exact directory, and 
thereforce should not add new file inner2.
+exec chezmoi re-add --recursive=false $HOME/outer-dir
+! exists $CHEZMOISOURCEDIR/outer-dir/exact_exact-inner/inner2
+
+# re-add with recursive (default) SHOULD process nested exact directory
+exec chezmoi re-add $HOME/outer-dir
+exists $CHEZMOISOURCEDIR/outer-dir/exact_exact-inner/inner2
+cmp $CHEZMOISOURCEDIR/outer-dir/exact_exact-inner/inner2 golden/inner2
+
+# verify no diff
+exec chezmoi diff
+! stdout .
+
+# test nested exact directories (both parent and child are exact)
+exec chezmoi add --exact $HOME/exact-outer
+exists $CHEZMOISOURCEDIR/exact_exact-outer/exact_exact-inner/nested1
+
+# add a new file to the nested exact directory
+cp golden/nested2 $HOME/exact-outer/exact-inner/nested2
+
+# re-add should process both exact directories and add the new file
+exec chezmoi re-add
+exists $CHEZMOISOURCEDIR/exact_exact-outer/exact_exact-inner/nested2
+cmp $CHEZMOISOURCEDIR/exact_exact-outer/exact_exact-inner/nested2 
golden/nested2
+
+# verify no diff
+exec chezmoi diff
+! stdout .
+
+-- golden/inner2 --
+# contents of inner2
+-- golden/nested2 --
+# contents of nested2
+-- golden/test1 --
+# contents of test1
+-- golden/test2 --
+# contents of test2
+-- golden/test3 --
+# contents of test3
+-- home/user/exact-outer/exact-inner/nested1 --
+# contents of nested1
+-- home/user/exact-outer/outer1 --
+# contents of outer1
+-- home/user/outer-dir/exact-inner/inner1 --
+# contents of inner1
+-- home/user/outer-dir/file1 --
+# contents of outer file1
+-- home/user/test-dir/test1 --
+# contents of test1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.66.1/internal/cmd/util.go 
new/chezmoi-2.67.0/internal/cmd/util.go
--- old/chezmoi-2.66.1/internal/cmd/util.go     2025-10-19 23:33:16.000000000 
+0200
+++ new/chezmoi-2.67.0/internal/cmd/util.go     2025-11-02 19:55:46.000000000 
+0100
@@ -97,8 +97,8 @@
 
 // pluralize returns the English plural form of singular.
 func pluralize(singular string) string {
-       if strings.HasSuffix(singular, "y") {
-               return strings.TrimSuffix(singular, "y") + "ies"
+       if prefix, found := strings.CutSuffix(singular, "y"); found {
+               return prefix + "ies"
        }
        return singular + "s"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.66.1/internal/cmds/generate-install.sh/install.sh.tmpl 
new/chezmoi-2.67.0/internal/cmds/generate-install.sh/install.sh.tmpl
--- old/chezmoi-2.66.1/internal/cmds/generate-install.sh/install.sh.tmpl        
2025-10-19 23:33:16.000000000 +0200
+++ new/chezmoi-2.67.0/internal/cmds/generate-install.sh/install.sh.tmpl        
2025-11-02 19:55:46.000000000 +0100
@@ -302,7 +302,7 @@
        checksums="${2}"
        basename="${target##*/}"
 
-       want="$(grep "${basename}" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
+       want="$(grep "${basename}\$" "${checksums}" 2>/dev/null | tr '\t' ' ' | 
cut -d ' ' -f 1)"
        if [ -z "${want}" ]; then
                log_err "hash_sha256_verify unable to find checksum for 
${target} in ${checksums}"
                return 1

++++++ chezmoi.obsinfo ++++++
--- /var/tmp/diff_new_pack.g9bK5V/_old  2025-11-04 18:42:00.692554358 +0100
+++ /var/tmp/diff_new_pack.g9bK5V/_new  2025-11-04 18:42:00.696554527 +0100
@@ -1,5 +1,5 @@
 name: chezmoi
-version: 2.66.1
-mtime: 1760909596
-commit: 94b95eb0b6bf91e48dd7b584a80ad60d44d8de4d
+version: 2.67.0
+mtime: 1762109746
+commit: 8591960c5b55b27d3806c6754232e1a6980957e1
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/chezmoi/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.chezmoi.new.1980/vendor.tar.gz differ: char 29, 
line 1

Reply via email to