Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package chezmoi for openSUSE:Factory checked 
in at 2023-02-13 16:41:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/chezmoi (Old)
 and      /work/SRC/openSUSE:Factory/.chezmoi.new.1848 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "chezmoi"

Mon Feb 13 16:41:30 2023 rev:14 rq:1065522 version:2.30.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/chezmoi/chezmoi.changes  2023-02-07 
18:51:01.883759317 +0100
+++ /work/SRC/openSUSE:Factory/.chezmoi.new.1848/chezmoi.changes        
2023-02-13 16:43:24.780256882 +0100
@@ -1,0 +2,9 @@
+Mon Feb 13 14:18:00 UTC 2023 - Filippo Bonazzi <filippo.bona...@suse.com>
+
+- Update to version 2.30.1:
+  * Add deleteValueAtPath and pruneEmptyDicts template functions
+  * feat: Extend toPrettyJson template function to take indent
+  * fix: Fix chezmoi target-path when using .chezmoiroot
+  * chore: Use strings.Cut{Prefix,Suffix}
+
+-------------------------------------------------------------------

Old:
----
  chezmoi-2.30.0.obscpio

New:
----
  chezmoi-2.30.1.obscpio

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

Other differences:
------------------
++++++ chezmoi.spec ++++++
--- /var/tmp/diff_new_pack.HfxlPn/_old  2023-02-13 16:43:25.408260582 +0100
+++ /var/tmp/diff_new_pack.HfxlPn/_new  2023-02-13 16:43:25.412260605 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           chezmoi
-Version:        2.30.0
+Version:        2.30.1
 Release:        0
 Summary:        A multi-host manager for dotfiles
 License:        MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.HfxlPn/_old  2023-02-13 16:43:25.448260817 +0100
+++ /var/tmp/diff_new_pack.HfxlPn/_new  2023-02-13 16:43:25.452260842 +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.30.0</param>
+    <param name="revision">v2.30.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
   </service>

++++++ chezmoi-2.30.0.obscpio -> chezmoi-2.30.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/deleteValueAtPath.md
 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/deleteValueAtPath.md
--- 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/deleteValueAtPath.md
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/deleteValueAtPath.md
        2023-02-11 19:06:40.000000000 +0100
@@ -0,0 +1,16 @@
+# `deleteValueAtPath` *path* *dict*
+
+`deleteValueAtPath` modifies *dict* to delete the value at *path* and returns
+*dict*. *path* can be either a string containing a `.`-separated list of keys 
or
+a list of keys.
+
+If *path* does not exist in *dict* then `deleteValueAtPath` returns *dict*
+unchanged.
+
+!!! example
+
+    ```
+    {{ dict "outer" (dict "inner" "value") | deleteValueAtPath "outer.inner" | 
toJson }}
+    {{ dict | setValueAtPath "key1" "value1" | setValueAtPath "key2.nestedKey" 
"value2" | toJson }}
+    {{ dict | setValueAtPath (list "key2" "nestedKey") "value2" | toJson }}
+    ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/pruneEmptyDicts.md
 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/pruneEmptyDicts.md
--- 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/pruneEmptyDicts.md
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/pruneEmptyDicts.md
  2023-02-11 19:06:40.000000000 +0100
@@ -0,0 +1,11 @@
+# `pruneEmptyDicts` *dict*
+
+`pruneEmptyDicts` modifies *dict* to remove nested empty dicts. Properties are
+pruned from the bottom up, so any nested dicts that themselves only contain
+empty dicts are pruned.
+
+!!! example
+
+    ```
+    {{ dict "key" "value" inner (dict) | pruneEmptyDicts | toJson }}
+    ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/toPrettyJson.md
 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/toPrettyJson.md
--- 
old/chezmoi-2.30.0/assets/chezmoi.io/docs/reference/templates/functions/toPrettyJson.md
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/chezmoi-2.30.1/assets/chezmoi.io/docs/reference/templates/functions/toPrettyJson.md
     2023-02-11 19:06:40.000000000 +0100
@@ -0,0 +1,11 @@
+# `toPrettyJson` [*indent*] *value*
+
+`toPrettyJson` returns the JSON representation of *value*. The optional 
*indent*
+specifies how much nested elements are indented relative to their parent.
+*indent* defaults to two spaces.
+
+!!! examples
+
+    ```
+    {{ dict "a" (dict "b" "c") | toPrettyJson "\t" }}
+    ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/chezmoi.io/mkdocs.yml 
new/chezmoi-2.30.1/assets/chezmoi.io/mkdocs.yml
--- old/chezmoi-2.30.0/assets/chezmoi.io/mkdocs.yml     2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/assets/chezmoi.io/mkdocs.yml     2023-02-11 
19:06:40.000000000 +0100
@@ -176,6 +176,7 @@
       - comment: reference/templates/functions/comment.md
       - completion: reference/templates/functions/completion.md
       - decrypt: reference/templates/functions/decrypt.md
+      - deleteValueAtPath: reference/templates/functions/deleteValueAtPath.md
       - encrypt: reference/templates/functions/encrypt.md
       - eqFold: reference/templates/functions/eqFold.md
       - fromIni: reference/templates/functions/fromIni.md
@@ -192,11 +193,13 @@
       - lstat: reference/templates/functions/lstat.md
       - mozillaInstallHash: reference/templates/functions/mozillaInstallHash.md
       - output: reference/templates/functions/output.md
+      - pruneEmptyDicts: reference/templates/functions/pruneEmptyDicts.md
       - quoteList: reference/templates/functions/quoteList.md
       - replaceAllRegex: reference/templates/functions/replaceAllRegex.md
       - setValueAtPath: reference/templates/functions/setValueAtPath.md
       - stat: reference/templates/functions/stat.md
       - toIni: reference/templates/functions/toIni.md
+      - toPrettyJson: reference/templates/functions/toPrettyJson.md
       - toToml: reference/templates/functions/toToml.md
       - toYaml: reference/templates/functions/toYaml.md
     - GitHub functions:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/docker/test.sh 
new/chezmoi-2.30.1/assets/docker/test.sh
--- old/chezmoi-2.30.0/assets/docker/test.sh    2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/assets/docker/test.sh    2023-02-11 19:06:40.000000000 
+0100
@@ -4,19 +4,19 @@
 
 cd ../..
 for distribution in "$@"; do
-    echo "${distribution}"
-    dockerfile="assets/docker/${distribution}.Dockerfile"
-    if [ ! -f "${dockerfile}" ]; then
-        echo "${dockerfile} not found"
-        exit 1
-    fi
-    image="$(docker build . -f "assets/docker/${distribution}.Dockerfile" -q)"
-    docker run \
-        --env "CHEZMOI_GITHUB_ACCESS_TOKEN=${CHEZMOI_GITHUB_ACCESS_TOKEN-}" \
-        --env "CHEZMOI_GITHUB_TOKEN=${CHEZMOI_GITHUB_TOKEN-}" \
-        --env "GITHUB_ACCESS_TOKEN=${GITHUB_ACCESS_TOKEN-}" \
-        --env "GITHUB_TOKEN=${GITHUB_TOKEN-}" \
-        --rm \
-        --volume "${PWD}:/chezmoi" \
-        "${image}"
+       echo "${distribution}"
+       dockerfile="assets/docker/${distribution}.Dockerfile"
+       if [ ! -f "${dockerfile}" ]; then
+               echo "${dockerfile} not found"
+               exit 1
+       fi
+       image="$(docker build . -f "assets/docker/${distribution}.Dockerfile" 
-q)"
+       docker run \
+               --env 
"CHEZMOI_GITHUB_ACCESS_TOKEN=${CHEZMOI_GITHUB_ACCESS_TOKEN-}" \
+               --env "CHEZMOI_GITHUB_TOKEN=${CHEZMOI_GITHUB_TOKEN-}" \
+               --env "GITHUB_ACCESS_TOKEN=${GITHUB_ACCESS_TOKEN-}" \
+               --env "GITHUB_TOKEN=${GITHUB_TOKEN-}" \
+               --rm \
+               --volume "${PWD}:/chezmoi" \
+               "${image}"
 done
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/scripts/generate-commit.sh 
new/chezmoi-2.30.1/assets/scripts/generate-commit.sh
--- old/chezmoi-2.30.0/assets/scripts/generate-commit.sh        2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/assets/scripts/generate-commit.sh        2023-02-11 
19:06:40.000000000 +0100
@@ -16,5 +16,5 @@
 if [ -z "${output}" ]; then
        echo "${commit}"
 else
-       echo "${commit}" > "${output}"
+       echo "${commit}" >"${output}"
 fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/scripts/install.sh 
new/chezmoi-2.30.1/assets/scripts/install.sh
--- old/chezmoi-2.30.0/assets/scripts/install.sh        2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/assets/scripts/install.sh        2023-02-11 
19:06:40.000000000 +0100
@@ -60,6 +60,7 @@
                                GOOS_EXTRA="-musl"
                                ;;
                        esac
+                       ;;
                esac
                ;;
        windows)
@@ -187,7 +188,7 @@
 get_libc() {
        if is_command ldd; then
                case "$(ldd --version 2>&1 | tr '[:upper:]' '[:lower:]')" in
-               *glibc*|*"gnu libc"*)
+               *glibc* | *"gnu libc"*)
                        printf glibc
                        return
                        ;;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/scripts/stow-to-chezmoi.sh 
new/chezmoi-2.30.1/assets/scripts/stow-to-chezmoi.sh
--- old/chezmoi-2.30.0/assets/scripts/stow-to-chezmoi.sh        2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/assets/scripts/stow-to-chezmoi.sh        2023-02-11 
19:06:40.000000000 +0100
@@ -38,24 +38,24 @@
 trap 'exit' INT TERM
 
 find "${BASEDIR}" \! -path '*
-*' \! -path "${BASEDIR}/${STOWDIR}*" -type l >"${work_file}" || \
+*' \! -path "${BASEDIR}/${STOWDIR}*" -type l >"${work_file}" ||
        printf "Find skipped some files\n" >&2
 
 while read -r f; do
        target="$("${READLINK}" -f -- "${f}" || :)"
        case "${target}" in
-               "${BASEDIR}/${STOWDIR}/"*)
-                       printf 'Add %s\n' "${f}" >&2
-                       printf '%s\n' "${f}" >>"${act_file}"
-                       ;;
+       "${BASEDIR}/${STOWDIR}/"*)
+               printf 'Add %s\n' "${f}" >&2
+               printf '%s\n' "${f}" >>"${act_file}"
+               ;;
        esac
 done <"${work_file}"
 
 printf 'Migrate the above to chezmoi? y/N ' >&2
 read -r migrate
 case "${migrate}" in
-       [Yy]*) printf 'Migrating...\n' >&2 ;;
-       *) exit 1 ;;
+[Yy]*) printf 'Migrating...\n' >&2 ;;
+*) exit 1 ;;
 esac
 
 mkdir -p -- "${BASEDIR}/.local/share"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/templates/install.sh 
new/chezmoi-2.30.1/assets/templates/install.sh
--- old/chezmoi-2.30.0/assets/templates/install.sh      2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/assets/templates/install.sh      2023-02-11 
19:06:40.000000000 +0100
@@ -5,19 +5,19 @@
 set -eu
 
 if ! chezmoi="$(command -v chezmoi)"; then
-  bin_dir="${HOME}/.local/bin"
-  chezmoi="${bin_dir}/chezmoi"
-  echo "Installing chezmoi to '${chezmoi}'" >&2
-  if command -v curl >/dev/null; then
-    chezmoi_install_script="$(curl -fsSL get.chezmoi.io)"
-  elif command -v wget >/dev/null; then
-    chezmoi_install_script="$(wget -qO- get.chezmoi.io)"
-  else
-    echo "To install chezmoi, you must have curl or wget installed." >&2
-    exit 1
-  fi
-  sh -c "${chezmoi_install_script}" -- -b "${bin_dir}"
-  unset chezmoi_install_script bin_dir
+       bin_dir="${HOME}/.local/bin"
+       chezmoi="${bin_dir}/chezmoi"
+       echo "Installing chezmoi to '${chezmoi}'" >&2
+       if command -v curl >/dev/null; then
+               chezmoi_install_script="$(curl -fsSL get.chezmoi.io)"
+       elif command -v wget >/dev/null; then
+               chezmoi_install_script="$(wget -qO- get.chezmoi.io)"
+       else
+               echo "To install chezmoi, you must have curl or wget 
installed." >&2
+               exit 1
+       fi
+       sh -c "${chezmoi_install_script}" -- -b "${bin_dir}"
+       unset chezmoi_install_script bin_dir
 fi
 
 # POSIX way to get script's dir: https://stackoverflow.com/a/29834779/12156188
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/assets/vagrant/test.sh 
new/chezmoi-2.30.1/assets/vagrant/test.sh
--- old/chezmoi-2.30.0/assets/vagrant/test.sh   2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/assets/vagrant/test.sh   2023-02-11 19:06:40.000000000 
+0100
@@ -3,19 +3,19 @@
 set -eufo pipefail
 
 for os in "$@"; do
-    echo "${os}"
-    if [ ! -f "${os}.Vagrantfile" ]; then
-        echo "${os}.Vagrantfile not found"
-        exit 1
-    fi
-    export VAGRANT_VAGRANTFILE=assets/vagrant/${os}.Vagrantfile
-    if ! ( cd ../.. && vagrant up ); then
-        exit 1
-    fi
-    vagrant ssh -c "./test-chezmoi.sh"
-    vagrant_ssh_exit_code=$?
-    vagrant destroy -f || exit 1
-    if [ $vagrant_ssh_exit_code -ne 0 ]; then
-        exit $vagrant_ssh_exit_code
-    fi
+       echo "${os}"
+       if [ ! -f "${os}.Vagrantfile" ]; then
+               echo "${os}.Vagrantfile not found"
+               exit 1
+       fi
+       export VAGRANT_VAGRANTFILE=assets/vagrant/${os}.Vagrantfile
+       if ! (cd ../.. && vagrant up); then
+               exit 1
+       fi
+       vagrant ssh -c "./test-chezmoi.sh"
+       vagrant_ssh_exit_code=$?
+       vagrant destroy -f || exit 1
+       if [ $vagrant_ssh_exit_code -ne 0 ]; then
+               exit $vagrant_ssh_exit_code
+       fi
 done
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/internal/cmds/generate-install.sh/install.sh.tmpl 
new/chezmoi-2.30.1/internal/cmds/generate-install.sh/install.sh.tmpl
--- old/chezmoi-2.30.0/internal/cmds/generate-install.sh/install.sh.tmpl        
2023-02-06 09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/internal/cmds/generate-install.sh/install.sh.tmpl        
2023-02-11 19:06:40.000000000 +0100
@@ -60,6 +60,7 @@
                                GOOS_EXTRA="-musl"
                                ;;
                        esac
+                       ;;
                esac
                ;;
        windows)
@@ -162,7 +163,7 @@
 get_libc() {
        if is_command ldd; then
                case "$(ldd --version 2>&1 | tr '[:upper:]' '[:lower:]')" in
-               *glibc*|*"gnu libc"*)
+               *glibc* | *"gnu libc"*)
                        printf glibc
                        return
                        ;;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/attr.go 
new/chezmoi-2.30.1/pkg/chezmoi/attr.go
--- old/chezmoi-2.30.0/pkg/chezmoi/attr.go      2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/attr.go      2023-02-11 19:06:40.000000000 
+0100
@@ -78,37 +78,15 @@
 
 // parseDirAttr parses a single directory name in the source state.
 func parseDirAttr(sourceName string) DirAttr {
-       var (
-               name     = sourceName
-               exact    = false
-               external = false
-               private  = false
-               readOnly = false
-               remove   = false
-       )
-       if strings.HasPrefix(name, externalPrefix) {
-               name = mustTrimPrefix(name, externalPrefix)
-               external = true
-       }
-       if strings.HasPrefix(name, removePrefix) {
-               name = mustTrimPrefix(name, removePrefix)
-               remove = true
-       }
-       if strings.HasPrefix(name, exactPrefix) {
-               name = mustTrimPrefix(name, exactPrefix)
-               exact = true
-       }
-       if strings.HasPrefix(name, privatePrefix) {
-               name = mustTrimPrefix(name, privatePrefix)
-               private = true
-       }
-       if strings.HasPrefix(name, readOnlyPrefix) {
-               name = mustTrimPrefix(name, readOnlyPrefix)
-               readOnly = true
-       }
+       name := sourceName
+       name, external := CutPrefix(name, externalPrefix)
+       name, remove := CutPrefix(name, removePrefix)
+       name, exact := CutPrefix(name, exactPrefix)
+       name, private := CutPrefix(name, privatePrefix)
+       name, readOnly := CutPrefix(name, readOnlyPrefix)
        switch {
        case strings.HasPrefix(name, dotPrefix):
-               name = "." + mustTrimPrefix(name, dotPrefix)
+               name = "." + name[len(dotPrefix):]
        case strings.HasPrefix(name, literalPrefix):
                name = name[len(literalPrefix):]
        }
@@ -153,7 +131,7 @@
        }
        switch {
        case strings.HasPrefix(da.TargetName, "."):
-               sourceName += dotPrefix + mustTrimPrefix(da.TargetName, ".")
+               sourceName += dotPrefix + da.TargetName[len("."):]
        case dirPrefixRx.MatchString(da.TargetName):
                sourceName += literalPrefix + da.TargetName
        default:
@@ -191,109 +169,68 @@
        switch {
        case strings.HasPrefix(name, createPrefix):
                sourceFileType = SourceFileTypeCreate
-               name = mustTrimPrefix(name, createPrefix)
-               if strings.HasPrefix(name, encryptedPrefix) {
-                       name = mustTrimPrefix(name, encryptedPrefix)
-                       encrypted = true
-               }
-               if strings.HasPrefix(name, privatePrefix) {
-                       name = mustTrimPrefix(name, privatePrefix)
-                       private = true
-               }
-               if strings.HasPrefix(name, readOnlyPrefix) {
-                       name = mustTrimPrefix(name, readOnlyPrefix)
-                       readOnly = true
-               }
-               if strings.HasPrefix(name, executablePrefix) {
-                       name = mustTrimPrefix(name, executablePrefix)
-                       executable = true
-               }
+               name = name[len(createPrefix):]
+               name, encrypted = CutPrefix(name, encryptedPrefix)
+               name, private = CutPrefix(name, privatePrefix)
+               name, readOnly = CutPrefix(name, readOnlyPrefix)
+               name, executable = CutPrefix(name, executablePrefix)
        case strings.HasPrefix(name, removePrefix):
                sourceFileType = SourceFileTypeRemove
-               name = mustTrimPrefix(name, removePrefix)
+               name = name[len(removePrefix):]
        case strings.HasPrefix(name, runPrefix):
                sourceFileType = SourceFileTypeScript
-               name = mustTrimPrefix(name, runPrefix)
+               name = name[len(runPrefix):]
                switch {
                case strings.HasPrefix(name, oncePrefix):
-                       name = mustTrimPrefix(name, oncePrefix)
+                       name = name[len(oncePrefix):]
                        condition = ScriptConditionOnce
                case strings.HasPrefix(name, onChangePrefix):
-                       name = mustTrimPrefix(name, onChangePrefix)
+                       name = name[len(onChangePrefix):]
                        condition = ScriptConditionOnChange
                default:
                        condition = ScriptConditionAlways
                }
                switch {
                case strings.HasPrefix(name, beforePrefix):
-                       name = mustTrimPrefix(name, beforePrefix)
+                       name = name[len(beforePrefix):]
                        order = ScriptOrderBefore
                case strings.HasPrefix(name, afterPrefix):
-                       name = mustTrimPrefix(name, afterPrefix)
+                       name = name[len(afterPrefix):]
                        order = ScriptOrderAfter
                }
        case strings.HasPrefix(name, symlinkPrefix):
                sourceFileType = SourceFileTypeSymlink
-               name = mustTrimPrefix(name, symlinkPrefix)
+               name = name[len(symlinkPrefix):]
        case strings.HasPrefix(name, modifyPrefix):
                sourceFileType = SourceFileTypeModify
-               name = mustTrimPrefix(name, modifyPrefix)
-               if strings.HasPrefix(name, encryptedPrefix) {
-                       name = mustTrimPrefix(name, encryptedPrefix)
-                       encrypted = true
-               }
-               if strings.HasPrefix(name, privatePrefix) {
-                       name = mustTrimPrefix(name, privatePrefix)
-                       private = true
-               }
-               if strings.HasPrefix(name, readOnlyPrefix) {
-                       name = mustTrimPrefix(name, readOnlyPrefix)
-                       readOnly = true
-               }
-               if strings.HasPrefix(name, executablePrefix) {
-                       name = mustTrimPrefix(name, executablePrefix)
-                       executable = true
-               }
+               name = name[len(modifyPrefix):]
+               name, encrypted = CutPrefix(name, encryptedPrefix)
+               name, private = CutPrefix(name, privatePrefix)
+               name, readOnly = CutPrefix(name, readOnlyPrefix)
+               name, executable = CutPrefix(name, executablePrefix)
        default:
-               if strings.HasPrefix(name, encryptedPrefix) {
-                       name = mustTrimPrefix(name, encryptedPrefix)
-                       encrypted = true
-               }
-               if strings.HasPrefix(name, privatePrefix) {
-                       name = mustTrimPrefix(name, privatePrefix)
-                       private = true
-               }
-               if strings.HasPrefix(name, readOnlyPrefix) {
-                       name = mustTrimPrefix(name, readOnlyPrefix)
-                       readOnly = true
-               }
-               if strings.HasPrefix(name, emptyPrefix) {
-                       name = mustTrimPrefix(name, emptyPrefix)
-                       empty = true
-               }
-               if strings.HasPrefix(name, executablePrefix) {
-                       name = mustTrimPrefix(name, executablePrefix)
-                       executable = true
-               }
+               name, encrypted = CutPrefix(name, encryptedPrefix)
+               name, private = CutPrefix(name, privatePrefix)
+               name, readOnly = CutPrefix(name, readOnlyPrefix)
+               name, empty = CutPrefix(name, emptyPrefix)
+               name, executable = CutPrefix(name, executablePrefix)
        }
        switch {
        case strings.HasPrefix(name, dotPrefix):
-               name = "." + mustTrimPrefix(name, dotPrefix)
+               name = "." + name[len(dotPrefix):]
        case strings.HasPrefix(name, literalPrefix):
                name = name[len(literalPrefix):]
        }
        if encrypted {
-               name = strings.TrimSuffix(name, encryptedSuffix)
+               name, _ = CutSuffix(name, encryptedSuffix)
        }
        switch {
        case strings.HasSuffix(name, literalSuffix):
-               name = mustTrimSuffix(name, literalSuffix)
+               name = name[:len(name)-len(literalSuffix)]
        case strings.HasSuffix(name, TemplateSuffix):
-               name = mustTrimSuffix(name, TemplateSuffix)
+               name = name[:len(name)-len(TemplateSuffix)]
                template = true
-               if strings.HasSuffix(name, literalSuffix) {
-                       name = mustTrimSuffix(name, literalSuffix)
-               }
+               name, _ = CutSuffix(name, literalSuffix)
        }
        return FileAttr{
                TargetName: name,
@@ -393,7 +330,7 @@
        }
        switch {
        case strings.HasPrefix(fa.TargetName, "."):
-               sourceName += dotPrefix + mustTrimPrefix(fa.TargetName, ".")
+               sourceName += dotPrefix + fa.TargetName[len("."):]
        case filePrefixRx.MatchString(fa.TargetName):
                sourceName += literalPrefix + fa.TargetName
        default:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/chezmoi.go 
new/chezmoi-2.30.1/pkg/chezmoi/chezmoi.go
--- old/chezmoi-2.30.0/pkg/chezmoi/chezmoi.go   2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/chezmoi.go   2023-02-11 19:06:40.000000000 
+0100
@@ -319,24 +319,6 @@
        return fmt.Sprintf("0o%o: unknown type", mode.Type())
 }
 
-// mustTrimPrefix is like strings.TrimPrefix but panics if s is not prefixed by
-// prefix.
-func mustTrimPrefix(s, prefix string) string {
-       if !strings.HasPrefix(s, prefix) {
-               panic(fmt.Sprintf("%s: not prefixed by %s", s, prefix))
-       }
-       return s[len(prefix):]
-}
-
-// mustTrimSuffix is like strings.TrimSuffix but panics if s is not suffixed by
-// suffix.
-func mustTrimSuffix(s, suffix string) string {
-       if !strings.HasSuffix(s, suffix) {
-               panic(fmt.Sprintf("%s: not suffixed by %s", s, suffix))
-       }
-       return s[:len(s)-len(suffix)]
-}
-
 // ripemd160Sum returns the RIPEMD-160 sum of data.
 func ripemd160Sum(data []byte) []byte {
        return ripemd160.New().Sum(data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/chezmoi_go1.19.go 
new/chezmoi-2.30.1/pkg/chezmoi/chezmoi_go1.19.go
--- old/chezmoi-2.30.0/pkg/chezmoi/chezmoi_go1.19.go    1970-01-01 
01:00:00.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/chezmoi_go1.19.go    2023-02-11 
19:06:40.000000000 +0100
@@ -0,0 +1,19 @@
+//go:build !go1.20
+
+package chezmoi
+
+import "strings"
+
+func CutPrefix(s, prefix string) (string, bool) {
+       if strings.HasPrefix(s, prefix) {
+               return s[len(prefix):], true
+       }
+       return s, false
+}
+
+func CutSuffix(s, suffix string) (string, bool) {
+       if strings.HasSuffix(s, suffix) {
+               return s[:len(s)-len(suffix)], true
+       }
+       return s, false
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/chezmoi_go1.20.go 
new/chezmoi-2.30.1/pkg/chezmoi/chezmoi_go1.20.go
--- old/chezmoi-2.30.0/pkg/chezmoi/chezmoi_go1.20.go    1970-01-01 
01:00:00.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/chezmoi_go1.20.go    2023-02-11 
19:06:40.000000000 +0100
@@ -0,0 +1,10 @@
+//go:build go1.20
+
+package chezmoi
+
+import "strings"
+
+var (
+       CutPrefix = strings.CutPrefix
+       CutSuffix = strings.CutSuffix
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/entrytypeset.go 
new/chezmoi-2.30.1/pkg/chezmoi/entrytypeset.go
--- old/chezmoi-2.30.0/pkg/chezmoi/entrytypeset.go      2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/entrytypeset.go      2023-02-11 
19:06:40.000000000 +0100
@@ -296,11 +296,7 @@
                if element == "" {
                        continue
                }
-               exclude := false
-               if strings.HasPrefix(element, "no") {
-                       exclude = true
-                       element = element[2:]
-               }
+               element, exclude := CutPrefix(element, "no")
                bit, ok := entryTypeBits[element]
                if !ok {
                        return fmt.Errorf("%s: unknown entry type", element)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/patternset.go 
new/chezmoi-2.30.1/pkg/chezmoi/patternset.go
--- old/chezmoi-2.30.0/pkg/chezmoi/patternset.go        2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/patternset.go        2023-02-11 
19:06:40.000000000 +0100
@@ -87,7 +87,7 @@
        }
        matchesSlice := allMatches.elements()
        for i, match := range matchesSlice {
-               matchesSlice[i] = mustTrimPrefix(filepath.ToSlash(match), 
prefix)
+               matchesSlice[i] = filepath.ToSlash(match)[len(prefix):]
        }
        sort.Strings(matchesSlice)
        return matchesSlice, nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/chezmoi/sourcestate.go 
new/chezmoi-2.30.1/pkg/chezmoi/sourcestate.go
--- old/chezmoi-2.30.0/pkg/chezmoi/sourcestate.go       2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/chezmoi/sourcestate.go       2023-02-11 
19:06:40.000000000 +0100
@@ -1212,9 +1212,9 @@
                        continue
                }
                include := patternSetInclude
-               if strings.HasPrefix(text, "!") {
+               text, ok := CutPrefix(text, "!")
+               if ok {
                        include = patternSetExclude
-                       text = mustTrimPrefix(text, "!")
                }
                pattern := dir.JoinString(text).String()
                if err := patternSet.add(pattern, include); err != nil {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/cmd/config.go 
new/chezmoi-2.30.1/pkg/cmd/config.go
--- old/chezmoi-2.30.0/pkg/cmd/config.go        2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/pkg/cmd/config.go        2023-02-11 19:06:40.000000000 
+0100
@@ -346,16 +346,21 @@
                stderr: os.Stderr,
        }
 
+       // Override sprig's toPrettyJson template function. Delete it from the
+       // template function map first to avoid a duplication function panic.
+       delete(c.templateFuncs, "toPrettyJson")
+
+       // The completion template function is added in persistentPreRunRootE as
+       // it needs a *cobra.Command, which we don't yet have.
        for key, value := range map[string]any{
-               "awsSecretsManager":    c.awsSecretsManagerTemplateFunc,
-               "awsSecretsManagerRaw": c.awsSecretsManagerRawTemplateFunc,
-               "bitwarden":            c.bitwardenTemplateFunc,
-               "bitwardenAttachment":  c.bitwardenAttachmentTemplateFunc,
-               "bitwardenFields":      c.bitwardenFieldsTemplateFunc,
-               "comment":              c.commentTemplateFunc,
-               // The completion template function is added in 
persistentPreRunRootE as
-               // it needs a *cobra.Command, which we don't yet have.
+               "awsSecretsManager":        c.awsSecretsManagerTemplateFunc,
+               "awsSecretsManagerRaw":     c.awsSecretsManagerRawTemplateFunc,
+               "bitwarden":                c.bitwardenTemplateFunc,
+               "bitwardenAttachment":      c.bitwardenAttachmentTemplateFunc,
+               "bitwardenFields":          c.bitwardenFieldsTemplateFunc,
+               "comment":                  c.commentTemplateFunc,
                "decrypt":                  c.decryptTemplateFunc,
+               "deleteValueAtPath":        c.deleteValueAtPathTemplateFunc,
                "encrypt":                  c.encryptTemplateFunc,
                "eqFold":                   c.eqFoldTemplateFunc,
                "fromIni":                  c.fromIniTemplateFunc,
@@ -395,6 +400,7 @@
                "passFields":               c.passFieldsTemplateFunc,
                "passRaw":                  c.passRawTemplateFunc,
                "passhole":                 c.passholeTemplateFunc,
+               "pruneEmptyDicts":          c.pruneEmptyDictsTemplateFunc,
                "quoteList":                c.quoteListTemplateFunc,
                "replaceAllRegex":          c.replaceAllRegexTemplateFunc,
                "secret":                   c.secretTemplateFunc,
@@ -402,6 +408,7 @@
                "setValueAtPath":           c.setValueAtPathTemplateFunc,
                "stat":                     c.statTemplateFunc,
                "toIni":                    c.toIniTemplateFunc,
+               "toPrettyJson":             c.toPrettyJsonTemplateFunc,
                "toToml":                   c.toTomlTemplateFunc,
                "toYaml":                   c.toYamlTemplateFunc,
                "vault":                    c.vaultTemplateFunc,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/cmd/targetpathcmd.go 
new/chezmoi-2.30.1/pkg/cmd/targetpathcmd.go
--- old/chezmoi-2.30.0/pkg/cmd/targetpathcmd.go 2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/pkg/cmd/targetpathcmd.go 2023-02-11 19:06:40.000000000 
+0100
@@ -33,7 +33,7 @@
                        return err
                }
 
-               argRelPath, err := argAbsPath.TrimDirPrefix(c.SourceDirAbsPath)
+               argRelPath, err := argAbsPath.TrimDirPrefix(c.sourceDirAbsPath)
                if err != nil {
                        return err
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/cmd/templatefuncs.go 
new/chezmoi-2.30.1/pkg/cmd/templatefuncs.go
--- old/chezmoi-2.30.0/pkg/cmd/templatefuncs.go 2023-02-06 09:14:47.000000000 
+0100
+++ new/chezmoi-2.30.1/pkg/cmd/templatefuncs.go 2023-02-11 19:06:40.000000000 
+0100
@@ -2,6 +2,7 @@
 
 import (
        "encoding/hex"
+       "encoding/json"
        "errors"
        "fmt"
        "io"
@@ -96,6 +97,29 @@
        return builder.String()
 }
 
+func (c *Config) deleteValueAtPathTemplateFunc(path string, dict 
map[string]any) any {
+       keys, lastKey, err := keysFromPath(path)
+       if err != nil {
+               panic(err)
+       }
+
+       currentMap := dict
+       for _, key := range keys {
+               value, ok := currentMap[key]
+               if !ok {
+                       return dict
+               }
+               nestedMap, ok := value.(map[string]any)
+               if !ok {
+                       return dict
+               }
+               currentMap = nestedMap
+       }
+       delete(currentMap, lastKey)
+
+       return dict
+}
+
 func (c *Config) eqFoldTemplateFunc(first, second string, more ...string) bool 
{
        if strings.EqualFold(first, second) {
                return true
@@ -289,6 +313,11 @@
        return string(output)
 }
 
+func (c *Config) pruneEmptyDictsTemplateFunc(dict map[string]any) 
map[string]any {
+       pruneEmptyMaps(dict)
+       return dict
+}
+
 func (c *Config) quoteListTemplateFunc(list []any) []string {
        result := make([]string, 0, len(list))
        for _, elem := range list {
@@ -385,6 +414,34 @@
        return builder.String()
 }
 
+//nolint:revive,stylecheck
+func (c *Config) toPrettyJsonTemplateFunc(args ...any) string {
+       var (
+               indent = "  "
+               value  any
+       )
+       switch len(args) {
+       case 1:
+               value = args[0]
+       case 2:
+               var ok bool
+               indent, ok = args[0].(string)
+               if !ok {
+                       panic(fmt.Errorf("arg 1: expected a string, got a %T", 
args[0]))
+               }
+               value = args[1]
+       default:
+               panic(fmt.Errorf("expected 1 or 2 arguments, got %d", 
len(args)))
+       }
+       var builder strings.Builder
+       encoder := json.NewEncoder(&builder)
+       encoder.SetIndent("", indent)
+       if err := encoder.Encode(value); err != nil {
+               panic(err)
+       }
+       return builder.String()
+}
+
 func (c *Config) toTomlTemplateFunc(data any) string {
        toml, err := chezmoi.FormatTOML.Marshal(data)
        if err != nil {
@@ -564,6 +621,21 @@
        return false
 }
 
+// pruneEmptyMaps prunes all empty maps from m and returns if m is now empty
+// itself.
+func pruneEmptyMaps(m map[string]any) bool {
+       for key, value := range m {
+               nestedMap, ok := value.(map[string]any)
+               if !ok {
+                       continue
+               }
+               if pruneEmptyMaps(nestedMap) {
+                       delete(m, key)
+               }
+       }
+       return len(m) == 0
+}
+
 func sortedKeys[K constraints.Ordered, V any](m map[K]V) []K {
        keys := maps.Keys(m)
        slices.Sort(keys)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/chezmoi-2.30.0/pkg/cmd/templatefuncs_test.go 
new/chezmoi-2.30.1/pkg/cmd/templatefuncs_test.go
--- old/chezmoi-2.30.0/pkg/cmd/templatefuncs_test.go    2023-02-06 
09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/cmd/templatefuncs_test.go    2023-02-11 
19:06:40.000000000 +0100
@@ -54,6 +54,145 @@
        }
 }
 
+func TestDeleteValueAtPathTemplateFunc(t *testing.T) {
+       for _, tc := range []struct {
+               name        string
+               dict        map[string]any
+               path        string
+               expected    any
+               expectedErr string
+       }{
+               {
+                       name:        "empty",
+                       expectedErr: "empty path",
+               },
+               {
+                       name: "outer",
+                       dict: map[string]any{
+                               "key": "value",
+                       },
+                       path:     "key",
+                       expected: map[string]any{},
+               },
+               {
+                       name: "inner",
+                       dict: map[string]any{
+                               "key1": map[string]any{
+                                       "key2a": "value2a",
+                                       "key2b": "value2b",
+                               },
+                       },
+                       path: "key1.key2a",
+                       expected: map[string]any{
+                               "key1": map[string]any{
+                                       "key2b": "value2b",
+                               },
+                       },
+               },
+               {
+                       name: "missing",
+                       dict: map[string]any{
+                               "key": "value",
+                       },
+                       path: "missingKey",
+                       expected: map[string]any{
+                               "key": "value",
+                       },
+               },
+               {
+                       name: "missing_inner",
+                       dict: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": 0,
+                               },
+                       },
+                       path: "key1.key3",
+                       expected: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": 0,
+                               },
+                       },
+               },
+               {
+                       name: "missing_depth2",
+                       dict: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": map[string]any{
+                                               "key3": 0,
+                                       },
+                               },
+                       },
+                       path: "key1.key2.missingKey",
+                       expected: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": map[string]any{
+                                               "key3": 0,
+                                       },
+                               },
+                       },
+               },
+               {
+                       name: "not_an_inner_dict",
+                       dict: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": 0,
+                               },
+                       },
+                       path: "key1.key2.key3",
+                       expected: map[string]any{
+                               "key1": map[string]any{
+                                       "key2": 0,
+                               },
+                       },
+               },
+       } {
+               t.Run(tc.name, func(t *testing.T) {
+                       var c Config
+                       if tc.expectedErr == "" {
+                               actual := 
c.deleteValueAtPathTemplateFunc(tc.path, tc.dict)
+                               assert.Equal(t, tc.expected, actual)
+                       } else {
+                               assert.PanicsWithError(t, tc.expectedErr, 
func() {
+                                       
c.deleteValueAtPathTemplateFunc(tc.path, tc.dict)
+                               })
+                       }
+               })
+       }
+}
+
+func TestPruneEmptyDicts(t *testing.T) {
+       for _, tc := range []struct {
+               name     string
+               dict     map[string]any
+               expected map[string]any
+       }{
+               {
+                       name:     "nil",
+                       dict:     nil,
+                       expected: nil,
+               },
+               {
+                       name:     "empty",
+                       dict:     map[string]any{},
+                       expected: map[string]any{},
+               },
+               {
+                       name: "nested_empty",
+                       dict: map[string]any{
+                               "key1": map[string]any{},
+                               "key2": 0,
+                       },
+                       expected: map[string]any{
+                               "key2": 0,
+                       },
+               },
+       } {
+               t.Run(tc.name, func(t *testing.T) {
+                       assert.Equal(t, tc.expected, 
(&Config{}).pruneEmptyDictsTemplateFunc(tc.dict))
+               })
+       }
+}
+
 func TestSetValueAtPathTemplateFunc(t *testing.T) {
        for _, tc := range []struct {
                name        string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/pkg/cmd/testdata/scripts/issue2752.txtar 
new/chezmoi-2.30.1/pkg/cmd/testdata/scripts/issue2752.txtar
--- old/chezmoi-2.30.0/pkg/cmd/testdata/scripts/issue2752.txtar 1970-01-01 
01:00:00.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/cmd/testdata/scripts/issue2752.txtar 2023-02-11 
19:06:40.000000000 +0100
@@ -0,0 +1,10 @@
+[windows] skip 'uses forward slashes in paths'
+
+# test that chezmoi target-path does not include .chezmoiroot in the output
+exec chezmoi target-path $CHEZMOISOURCEDIR${/}home${/}dot_file
+stdout ${HOME@R}/\.file
+
+-- home/user/.local/share/chezmoi/.chezmoiroot --
+home
+-- home/user/.local/share/chezmoi/home/dot_file --
+# contents of .file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/chezmoi-2.30.0/pkg/cmd/testdata/scripts/templatefuncs.txtar 
new/chezmoi-2.30.1/pkg/cmd/testdata/scripts/templatefuncs.txtar
--- old/chezmoi-2.30.0/pkg/cmd/testdata/scripts/templatefuncs.txtar     
2023-02-06 09:14:47.000000000 +0100
+++ new/chezmoi-2.30.1/pkg/cmd/testdata/scripts/templatefuncs.txtar     
2023-02-11 19:06:40.000000000 +0100
@@ -14,6 +14,11 @@
 exec chezmoi execute-template '{{ completion "zsh" }}'
 stdout '^# zsh completion for chezmoi'
 
+# test deleteValueAtPath template function
+exec chezmoi execute-template '{{ dict "a" (dict "b" (dict "c" 1 "d" 2)) | 
deleteValueAtPath "a.b.c" | toJson }}'
+rmfinalnewline golden/deleteValueAtPath
+cmp stdout golden/deleteValueAtPath
+
 # test eqFold template function
 exec chezmoi execute-template '{{ eqFold "foo" "Foo" "FOO" }}'
 stdout '^true$'
@@ -79,6 +84,11 @@
 [!(windows||illumos)] stderr 'error calling output: .*/false: exit status 1'
 [illumos] stderr 'error calling output: .*/false: exit status 255'
 
+# test pruneEmptyDicts template function
+exec chezmoi execute-template '{{ dict "key1" "value1" "key2" (dict) | 
pruneEmptyDicts | toJson }}'
+rmfinalnewline golden/pruneEmptyDicts
+cmp stdout golden/pruneEmptyDicts
+
 # test replaceAllRegex template function
 exec chezmoi execute-template '{{ "foo bar baz" | replaceAllRegex "ba" "BA" }}'
 stdout 'foo BAr BAz'
@@ -111,6 +121,10 @@
 exec chezmoi execute-template '{{ dict "key" "value" | toToml }}'
 stdout '^key = .value.$'
 
+# test toPrettyJson template function
+exec chezmoi execute-template '{{ dict "a" (dict "b" "c") | toPrettyJson "    
" }}'
+cmp stdout golden/toPrettyJson
+
 # test fromYaml template function
 exec chezmoi execute-template '{{ (fromYaml "key1: value1\nkey2: value2").key2 
}}'
 stdout '^value2$'
@@ -175,6 +189,8 @@
 -- golden/comment --
 # line1
 # line2
+-- golden/deleteValueAtPath --
+{"a":{"b":{"d":2}}}
 -- golden/expected --
 255
 -- golden/glob --
@@ -184,6 +200,8 @@
 # contents of .include
 -- golden/include-relpath --
 # contents of .local/share/chezmoi/.include
+-- golden/pruneEmptyDicts --
+{"key1":"value1"}
 -- golden/setValueAtPath --
 {"key1":{"key2":"value2"}}
 -- golden/toIni --
@@ -191,6 +209,12 @@
 
 [section]
 subkey = subvalue
+-- golden/toPrettyJson --
+{
+    "a": {
+        "b": "c"
+    }
+}
 -- home/user/.include --
 # contents of .include
 -- home/user/.local/share/chezmoi/.chezmoitemplates/template --

++++++ chezmoi.obsinfo ++++++
--- /var/tmp/diff_new_pack.HfxlPn/_old  2023-02-13 16:43:25.884263386 +0100
+++ /var/tmp/diff_new_pack.HfxlPn/_new  2023-02-13 16:43:25.888263410 +0100
@@ -1,5 +1,5 @@
 name: chezmoi
-version: 2.30.0
-mtime: 1675671287
-commit: d16ce211bcd2c55cc1c9ad8df13f3222944caf5f
+version: 2.30.1
+mtime: 1676138800
+commit: ff0c704a9068c81b3ad301236d730fefcd9ce98c
 

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

Reply via email to