Skip to content

Commit 48418aa

Browse files
committed
Greatly improve performance in a repository with many files #193
Greatly improve performance in a repository with many files for pre-commit safety check, encrypted file listing, and showing raw file. Performance wins are achieved by avoiding creation of subshells in a tight loop when processing Git's `ls-files` and instead using a smart piping alternative approach. Thanks Andrei!
2 parents 48b801d + 661d653 commit 48418aa

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ system, you must also run the `--upgrade` command in each repository:
3838

3939
- Improve check for incorrect password to avoid false report when transcrypt
4040
init is run with --force in a repo containing dirty files & add tests (#196)
41+
- Greatly improve performance in a repository with many files for pre-commit
42+
safety check, encrypted file listing, and showing raw file (#193)
4143

4244
### Fixed
4345

transcrypt

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,25 @@ _list_encrypted_files() {
170170
local strict_context=${1:-}
171171

172172
IFS=$'\n'
173-
# List files with -z option to disable quoting of filenames, then
174-
# immediately convert NUL-delimited filenames to be newline-delimited to be
175-
# compatibility with bash variables
176-
for file in $(git ls-files -z | tr '\0' '\n'); do
177-
# Check for the suffix ': filter: crypt' that identifies encrypted file
178-
local check
179-
check=$(git check-attr filter "$file" 2>/dev/null)
180-
181-
# Only output names of encrypted files matching the context, either
182-
# strictly (if $1 = "true") or loosely (if $1 is false or unset)
183-
if [[ "$strict_context" == "true" ]] &&
184-
[[ "$check" == *": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}" ]]; then
185-
echo "$file"
186-
elif [[ "$check" == *": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}"* ]]; then
187-
echo "$file"
188-
fi
189-
done
173+
# List files with -z option to disable quoting of filenames, then filter
174+
# for files marked for encryption (git check-attr + grep), then only keep
175+
# filenames (sed) then evaluate escaped characters like double-quotes,
176+
# backslash and control characters (eval) which are part of the output
177+
# regardless of core.quotePath=false as per
178+
# https://git-scm.com/docs/git-config#Documentation/git-config.txt-corequotePath
179+
git -c core.quotePath=false ls-files -z | tr '\0' '\n' |
180+
git -c core.quotePath=false check-attr filter --stdin 2>/dev/null |
181+
{
182+
# Only output names of encrypted files matching the context, either
183+
# strictly (if $1 = "true") or loosely (if $1 is false or unset)
184+
if [[ "$strict_context" == "true" ]]; then
185+
grep ": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}$" || true
186+
else
187+
grep ": filter: crypt${CONTEXT_CRYPT_SUFFIX:-}.*$" || true
188+
fi
189+
} |
190+
sed "s|: filter: crypt${CONTEXT_CRYPT_SUFFIX:-}.*||" |
191+
while read -r file; do eval "echo $file"; done
190192
}
191193

192194
# Detect OpenSSL major version 3 or later which requires a compatibility
@@ -1035,7 +1037,14 @@ upgrade_transcrypt() {
10351037
list_files() {
10361038
if [[ $IS_BARE == 'false' ]]; then
10371039
cd "$REPO" >/dev/null || die 1 'could not change into the "%s" directory' "$REPO"
1038-
_list_encrypted_files true
1040+
1041+
if [[ -z "$CONTEXT_CRYPT_SUFFIX" ]]; then
1042+
# Non-strict listing of files when context is unset / default
1043+
_list_encrypted_files
1044+
else
1045+
# Strict listing of files when a specific context is set
1046+
_list_encrypted_files true
1047+
fi
10391048
fi
10401049
}
10411050

0 commit comments

Comments
 (0)