-
Notifications
You must be signed in to change notification settings - Fork 1
/
pre-commit
150 lines (134 loc) · 4.33 KB
/
pre-commit
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/bin/sh
#
# The pre-commit hook script for Unity enforces the GitHub file size limit and ensures meta files stay in sync, as well as check that every folder & file
# marked to be ignored in .gitignore has an entry for its meta file to be ignored too.
# Based on this: https://github.com/kayy/git-pre-commit-hook-unity-assets & https://github.com/doitian/unity-git-hooks
#
#
# After cloning your repo, put this file into directory <your_repo>/.git/hooks. To disable, remove it from there.
ASSETS_DIR="$(git config --get unity3d.assets-dir || echo "Assets")"
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object.
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Redirect output to stderr.
exec 1>&2
# Ensure that there's no >100mb file in this checkin, which github won't allow.
CURRENT_DIR="$(pwd)"
HAS_ERROR=""
COMMIT_TEXT=$(git diff --cached --name-only | sort | uniq)
SAVEIFS=$IFS
IFS="
"
for file in $COMMIT_TEXT; do
file_size=$(du -m $CURRENT_DIR/$file | awk '{print $1}')
if [ "$file_size" -ge 100 ]; then
echo "$file is over 100MB."
HAS_ERROR="1"
fi
done
IFS=$SAVEIFS
if [ "$HAS_ERROR" != "" ]; then
echo "Can't commit, fix errors first." >&2
exit 1
fi
# Ensure meta files stay in sync.
git -c diff.renames=false diff --cached --name-only --diff-filter=A -z $against -- "$ASSETS_DIR" | while read -d $'\0' f; do
ext="${f##*.}"
base="${f%.*}"
filename="$(basename "$f")"
if [ "$ext" = "meta" ]; then
if [ $(git ls-files --cached -- "$base" | wc -l) = 0 ]; then
cat <<EOF
Error: Redudant meta file.
Meta file \`$f' is added, but \`$base' is not in the git index.
Please add \`$base' to git as well.
EOF
exit 1
fi
elif [ "${filename##.*}" != '' ]; then
p="$f"
while [ "$p" != "$ASSETS_DIR" ]; do
if [ $(git ls-files --cached -- "$p.meta" | wc -l) = 0 ]; then
cat <<EOF
Error: Missing meta file.
Asset \`$f' is added, but \`$p.meta' is not in the git index.
Please add \`$p.meta' to git as well.
EOF
exit 1
fi
p="${p%/*}"
done
fi
done
ret="$?"
if [ "$ret" != 0 ]; then
exit "$ret"
fi
git -c diff.renames=false diff --cached --name-only --diff-filter=D -z $against -- "$ASSETS_DIR" | while read -d $'\0' f; do
ext="${f##*.}"
base="${f%.*}"
if [ "$ext" = "meta" ]; then
if [ $(git ls-files --cached -- "$base" | wc -l) != 0 ]; then
cat <<EOF
Error: Missing meta file.
Meta file \`$f' is removed, but \`$base' is still in the git index.
Please revert the meta file or remove the asset file.
EOF
exit 1
fi
else
p="$f"
while [ "$p" != "$ASSETS_DIR" ]; do
if [ $(git ls-files --cached -- "$p" | wc -l) = 0 ] && [ $(git ls-files --cached -- "$p.meta" | wc -l) != 0 ]; then
cat <<EOF
Error: Redudant meta file.
Asset \`$f' is removed, but \`$p.meta' is still in the git index.
Please remove \`$p.meta' from git as well.
EOF
exit 1
fi
p="${p%/*}"
done
fi
done
ret="$?"
if [ "$ret" != 0 ]; then
exit "$ret"
fi
# Check if staged files contain the .gitignore file
if [ ! `git diff --name-only --cached | grep -- "\.gitignore"` ]; then
# Avoid expensive diff actions if there is no change in .gitignore
exit 0
fi
# New lines have the format {+xxxxx+}
raw_diff_output=`git diff --cached --word-diff=plain .gitignore | egrep "\{\+.*\+\}"`
# Prepare two strings: one for directories and one for meta files
for raw_entry in $raw_diff_output; do
# Strip leading and trailing separator "{+" and "+}"
if ((${#raw_entry} <= 4)); then
continue
else
e=${raw_entry:2:$((${#raw_entry}-4))}
is_meta=$((`echo $e | egrep ".*meta" | wc -l`))
if [ $is_meta -eq 0 ]; then
diff_output_dirs="${diff_output_dirs} ${e}"
else
diff_output_metas="${diff_output_metas} ${e}"
fi
fi
done
# Iterate over directories and check if there is an entry for the appropriate meta file
for i in $diff_output_dirs; do
# Meta file entries are often without directory, so strip the path
dir_name=`echo $i | egrep -o "/[^/]+$" | cut -d / -f 2`
echo $dir_name
has_meta_ignore=$((`echo $diff_output_metas | grep -- "$dir_name.meta" | wc -l`))
if [ ${has_meta_ignore} -eq 0 ]; then
echo "$dir_name found in .gitignore but not the corresponding meta file! Please add ${dir_name}.meta to .gitignore"
exit 1
fi
done