Skip to content

Commit 7e7c916

Browse files
feat: Improve performance during pre-commit --all (-a) run (antonbabenko#327)
1 parent a80d383 commit 7e7c916

11 files changed

+106
-7
lines changed

hooks/_common.sh

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,43 @@ function common::parse_cmdline {
5555
done
5656
}
5757

58+
#######################################################################
59+
# This is a workaround to improve performance when all files are passed
60+
# See: https://github.com/antonbabenko/pre-commit-terraform/issues/309
61+
# Arguments:
62+
# hook_id (string) hook ID, see `- id` for details in .pre-commit-hooks.yaml file
63+
# files (array) filenames to check
64+
# Outputs:
65+
# Return 0 if `-a|--all` arg was passed to `pre-commit`
66+
#######################################################################
67+
function common::is_hook_run_on_whole_repo {
68+
local -r hook_id="$1"
69+
shift 1
70+
local -a -r files=("$@")
71+
# get directory containing `.pre-commit-hooks.yaml` file
72+
local -r root_config_dir="$(dirname "$(dirname "$(realpath "${BASH_SOURCE[0]}")")")"
73+
# get included and excluded files from .pre-commit-hooks.yaml file
74+
local -r hook_config_block=$(sed -n "/^- id: $hook_id$/,/^$/p" "$root_config_dir/.pre-commit-hooks.yaml")
75+
local -r included_files=$(awk '$1 == "files:" {print $2; exit}' <<< "$hook_config_block")
76+
local -r excluded_files=$(awk '$1 == "exclude:" {print $2; exit}' <<< "$hook_config_block")
77+
# sorted string with the files passed to the hook by pre-commit
78+
local -r files_to_check=$(printf '%s\n' "${files[@]}" | sort | tr '\n' ' ')
79+
# git ls-files sorted string
80+
local all_files_that_can_be_checked
81+
82+
if [ -z "$excluded_files" ]; then
83+
all_files_that_can_be_checked=$(git ls-files | sort | grep -e "$included_files" | tr '\n' ' ')
84+
else
85+
all_files_that_can_be_checked=$(git ls-files | sort | grep -e "$included_files" | grep -v -e "$excluded_files" | tr '\n' ' ')
86+
fi
87+
88+
if [ "$files_to_check" == "$all_files_that_can_be_checked" ]; then
89+
return 0
90+
else
91+
return 1
92+
fi
93+
}
94+
5895
#######################################################################
5996
# Hook execution boilerplate logic which is common to hooks, that run
6097
# on per dir basis.
@@ -64,13 +101,23 @@ function common::parse_cmdline {
64101
# 3. Complete hook execution and return exit code
65102
# Arguments:
66103
# args (string with array) arguments that configure wrapped tool behavior
104+
# hook_id (string) hook ID, see `- id` for details in .pre-commit-hooks.yaml file
67105
# files (array) filenames to check
68106
#######################################################################
69107
function common::per_dir_hook {
70108
local -r args="$1"
71-
shift 1
109+
local -r hook_id="$2"
110+
shift 2
72111
local -a -r files=("$@")
73112

113+
# check is (optional) function defined
114+
if [ "$(type -t run_hook_on_whole_repo)" == function ] &&
115+
# check is hook run via `pre-commit run --all`
116+
common::is_hook_run_on_whole_repo "$hook_id" "${files[@]}"; then
117+
run_hook_on_whole_repo "$args"
118+
exit 0
119+
fi
120+
74121
# consume modified files passed from pre-commit so that
75122
# hook runs against only those relevant directories
76123
local index=0

hooks/infracost_breakdown.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
# shellcheck disable=SC2034 # Unused var.
7+
readonly HOOK_ID='infracost_breakdown'
48
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
59
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
610
# shellcheck source=_common.sh

hooks/terraform_docs.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
# shellcheck disable=SC2034 # Unused var.
7+
readonly HOOK_ID='terraform_docs'
48
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
59
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
610
# shellcheck source=_common.sh

hooks/terraform_fmt.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
# shellcheck disable=SC2034 # Unused var.
7+
readonly HOOK_ID='terraform_fmt'
48
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
59
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
610
# shellcheck source=_common.sh

hooks/terraform_providers_lock.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
set -eo pipefail
44

5+
# globals variables
6+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
7+
readonly HOOK_ID='terraform_providers_lock'
58
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
69
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
710
# shellcheck source=_common.sh
@@ -11,7 +14,7 @@ function main {
1114
common::initialize "$SCRIPT_DIR"
1215
common::parse_cmdline "$@"
1316
# shellcheck disable=SC2153 # False positive
14-
common::per_dir_hook "${ARGS[*]}" "${FILES[@]}"
17+
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
1518
}
1619

1720
#######################################################################

hooks/terraform_tflint.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
set -eo pipefail
44

5+
# globals variables
6+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
7+
readonly HOOK_ID='terraform_tflint'
58
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
69
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
710
# shellcheck source=_common.sh
@@ -14,7 +17,7 @@ function main {
1417
# shellcheck disable=SC2178 # It's the simplest syntax for that case
1518
ARGS=${ARGS[*]/__GIT_WORKING_DIR__/$(pwd)\/}
1619
# shellcheck disable=SC2128 # It's the simplest syntax for that case
17-
common::per_dir_hook "$ARGS" "${FILES[@]}"
20+
common::per_dir_hook "$ARGS" "$HOOK_ID" "${FILES[@]}"
1821
}
1922

2023
#######################################################################

hooks/terraform_tfsec.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
readonly HOOK_ID='terraform_tfsec'
47
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
58
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
69
# shellcheck source=_common.sh
@@ -13,7 +16,7 @@ function main {
1316
# shellcheck disable=SC2178 # It's the simplest syntax for that case
1417
ARGS=${ARGS[*]/__GIT_WORKING_DIR__/$(pwd)\/}
1518
# shellcheck disable=SC2128 # It's the simplest syntax for that case
16-
common::per_dir_hook "$ARGS" "${FILES[@]}"
19+
common::per_dir_hook "$ARGS" "$HOOK_ID" "${FILES[@]}"
1720
}
1821

1922
#######################################################################

hooks/terraform_validate.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
# shellcheck disable=SC2034 # Unused var.
7+
readonly HOOK_ID='terraform_validate'
48
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
59
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
610
# shellcheck source=_common.sh

hooks/terragrunt_fmt.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
readonly HOOK_ID='terragrunt_fmt'
47
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
58
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
69
# shellcheck source=_common.sh
@@ -10,7 +13,7 @@ function main {
1013
common::initialize "$SCRIPT_DIR"
1114
common::parse_cmdline "$@"
1215
# shellcheck disable=SC2153 # False positive
13-
common::per_dir_hook "${ARGS[*]}" "${FILES[@]}"
16+
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
1417
}
1518

1619
#######################################################################

hooks/terragrunt_validate.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/usr/bin/env bash
22
set -eo pipefail
33

4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
readonly HOOK_ID='terragrunt_validate'
47
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
58
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
69
# shellcheck source=_common.sh
@@ -10,7 +13,7 @@ function main {
1013
common::initialize "$SCRIPT_DIR"
1114
common::parse_cmdline "$@"
1215
# shellcheck disable=SC2153 # False positive
13-
common::per_dir_hook "${ARGS[*]}" "${FILES[@]}"
16+
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
1417
}
1518

1619
#######################################################################

0 commit comments

Comments
 (0)