-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathupdate-Makefiles
executable file
·103 lines (87 loc) · 3.81 KB
/
update-Makefiles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/bash
kTHIS_NAME=$(basename "$BASH_SOURCE")
kTHIS_DIR=$(dirname "$BASH_SOURCE")
kTHIS_DIR_NAME=$(cd "$kTHIS_DIR" && basename "$PWD")
unset CDPATH # to prevent unpredictable `cd` behavior
# Helper function for exiting with error message due to runtime error.
# die [errMsg [exitCode]]
# Default error message states context and indicates that execution is aborted. Default exit code is 1.
# Prefix for context is always prepended.
# Note: An error message is *always* printed; if you just want to exit with a specific code silently, use `exit n` directly.
die() {
echo "$kTHIS_NAME: ERROR: ${1:-"ABORTING due to unexpected error."}" 1>&2
exit ${2:-1} # Note: If the argument is non-numeric, the shell prints a warning and uses exit code 255.
}
# Helper function for exiting with error message due to invalid arguments.
# dieSyntax [errMsg]
# Default error message is provided, as is prefix and suffix; exit code is always 2.
dieSyntax() {
echo "$kTHIS_NAME: ARGUMENT ERROR: ${1:-"Invalid argument(s) specified."} Use -h for help." 1>&2
exit 2
}
# Regex for identifying Makefiles of the same type as this package's.
kMAKEFILE_ID_REGEX='^update-readme:'
kCUSTOM_MAKEFILE_REGEX='\[project-specific\]'
# Command-line help.
if [[ $1 == '--help' || $1 == '-h' ]]; then
cat <<EOF
SYNOPSIS
$kTHIS_NAME
DESCRIPTION
Updates Makefiles in this package's parent folder's subtree
with the Makefile from this package, assuming:
- they're not in hidden folders
- they're not inside 'node_module' folders
- they match a regex that identifies a Makefile as being
an (older) copy of this package's:
$kMAKEFILE_ID_REGEX
while not also being marked as containing project-specific modifications
$kCUSTOM_MAKEFILE_REGEX
Note that no attempt is made to compare timestamps.
You will be prompted for confirmation.
EOF
exit 0
fi
# Make sure that not too many arguments were specified.
(( $# == 0 )) || dieSyntax "Unexpected argument(s) specified."
# Change to the folder in which this script resides.
cd "$kTHIS_DIR" || die
echo "== Looking for Makefiles to update, relative to ${PWD/#$HOME/~}..."
# Run the same command twice:
# - the first time to simply ECHO the copy commands that WOULD be performed if confirmed by prompt.
# - the second time, if confirmed, to actually perform the copy commands.
cmdPrefix=( 'echo' '' )
for i in 0 1; do
if (( i == 0 )); then
# Read all candidate files into array ${files[@]}.
IFS=$'\n' read -r -d '' -a files < <(find .. ! -path '../'"$kTHIS_DIR_NAME"'/*' ! -path '*/node_modules/*' ! -path '*/.*' -name 'Makefile' -exec egrep -l "$kMAKEFILE_ID_REGEX" {} \;)
# Read those we must exclude - those with project-specific modifications - into ${filesToExclude[@]}
IFS=$'\n' read -r -d '' -a filesToExclude < <(egrep -l "$kCUSTOM_MAKEFILE_REGEX" "${files[@]}")
if [[ -n $filesToExclude ]]; then
cat <<EOF
===
WARNING: The following Makefiles are marked as having CUSTOM MODIFICATIONS
and will NOT be replaced - UPDATE THEM MANUALLY:
${filesToExclude[@]}
===
EOF
# Remove the files to exclude from ${files[@]}
IFS=$'\n' read -r -d '' -a files < <(printf '%s\n' "${files[@]}" | grep -Fvx "$(printf '%s\n' "${filesToExclude[@]}")" )
fi
fi
result=$(printf '%s\n' "${files[@]}" | xargs -I % ${cmdPrefix[i]} cp -p ./Makefile %) || die
if (( i == 0 )); then
[[ -n $result ]] || { die "No matching Makefiles found."; }
echo "$result"
while (( ! skipPrompt )); do
read -p "== PERFORM COPY COMMANDS as stated above? (y/N) " promptInput
[[ $promptInput =~ ^[yY]$ ]] && continue 2 # OK
[[ $promptInput =~ ^[nN]$ || -z $promptInput ]] && { echo "Aborted." 1>&2; exit 1; }
echo "Invalid input; please try again (^C to abort)." 1>&2
done
break
else
[[ -n $result ]] && echo $result
fi
done
echo '== Done.'