-
Notifications
You must be signed in to change notification settings - Fork 22
/
git-deploy-hook.sh
executable file
·231 lines (192 loc) · 5.4 KB
/
git-deploy-hook.sh
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/bin/bash
#
# git-deploy
#
# git post-receive hook to check out branches to a rsync destination
#
# Copyright 2012 K and H Research Company.
# License: WTFPL, any version or GNU General Public License, version 2+
#
##
## Documentation
##
## Installation
#
# To install git-deploy, copy this file to the hooks/ directory of a repository
# as "post-receive". Note that there is NO extension!
#
# You will need to set the git config variable deploy.$FOO.uri in order for this
# script to do anything. See the 'Configuration' section for more information.
#
# In order to function properly you must have rsync and the git-core suite on
# your system. If these are in non-standard locations or not within PATH you
# should set the RSYNC and GIT vars below. Other common utilities such as mkdir,
# cp, find, rm, umask, and tar are also required, but if you don't already have
# these you should probably see a psychiatrist.
#
## Configuration
#
# Several configuration options are supported by git-deploy, only one of which
# is mandatory(deploy.$FOO.uri). These options are all set via git-config.
# Several constants(see below) may be changed in the script itself, but you
# should not need to do so on a sane system. In all of the following, $FOO is
# the name of the branch which you wish to have automagically deployed.
#
# deploy.$FOO.opts
# Set of options to pass to rsync. git-deploy defaults to "-rt --delete",
# which will work (r)ecursively, attempt to maintain (t)imestamps, and
# (delete) files which do not exist in the source. You will likely want to
# add the --exclude=foo/ option to guard agaisnt deletion of ephermeral
# data directories used by your application. Please note that no injection
# checking is done against this option(patches welcome).
#
# deploy.$FOO.timestamps
# Whether or not to attempt to maintain timestamps on the work-tree which
# is checked-out. If true git-log is used to find the last commit which
# affected each path in the worktre, and then 'touch -m' is used to set
# the modification time to this date.
#
# deploy.$FOO.uri
# rsync URI which should be deployed to for branch $FOO. This can be any
# scheme which is known to 'rsync', including a local filesystem path, or
# a remote host(via SSH)
#
## Usage
#
# To use git-deploy simply push into your repo and git's hook system will take
# care of the rest. Errors and information will be shown to you as the script
# works its magic. If you wish to manually deploy you can do so by piping, on
# stdin, the same data that is fed to any git pre-receive hook.
#
## Todo
#
# 1) Split out the "meat" to a git-deploy script which can be invoked via the
# 'git' binary in a non-bare repository
#
# 2) Improve documentation wording - find an English teacher to run it by or
# something.
#
##
## Constants
##
# Path to the git binary
GIT=$(which git)
# Path to the rsync binary
RSYNC=$(which rsync)
# Temporary directory
TMP="/tmp"
# Repo directory
export GIT_DIR=$(pwd)
##
## Variables
##
##
## Sanity checks
##
## Existence of git
if [ ! -f "${GIT}" ]
then
# Error && exit
echo "Error: git binary not found"
exit 255
fi
## Existence of rsync
if [ ! -f "${RSYNC}" ]
then
# Error && exit
echo "Error: rsync binary not found"
exit 255
fi
## Existence of tmpdir
if [ ! -d "${TMP}" ]
then
# Error && exit
echo "Error: tmp directory not found"
exit 255
fi
##
## Runtime
##
# Create scratch dir
if mkdir "${TMP}/git-deploy.$$"
then
scratch="${TMP}/git-deploy.$$"
else
# Error && exit
echo "Error: unable to create scratch dir or already exists."
exit
fi
# Loop through stdin
while read old new ref
do
# Find branch name
branch=${ref#"refs/heads/"}
# Check branch name
if [ -z "${branch}" ]
then
echo "Refspec ${ref} is not a branch. Skipped!"
fi
# Don't attempt to handle deleted branches
if [ "${new}" = "0000000000000000000000000000000000000000" ]
then
# Error && skip branch
echo "Branch ${branch} deleted. Skipped!"
continue
fi
## Attempt to update
echo "Branch ${branch} updated. Deploying..."
# Deploy destination
dest=$(git config --get "deploy.${branch}.uri")
if [ -z "${dest}" ]
then
echo "Error: Destination not set! Deploy failed."
continue
fi
echo "Destination: "${dest}
# Rsync options
opts=$(git config --get "deploy.${branch}.opts")
if [ -z "${opts}" ]
then
opts="-rt --delete"
fi
echo "Options: "${opts}
# Create directory to archive into
mkdir "${scratch}/${branch}"
# Drop into scratchdir
cd "${scratch}/${branch}"
# Set umask
umask 007
# Get a copy of worktree
$GIT archive --format=tar ${new} | tar xf -
# Alter modification times?
timestamps=$(git config --bool --get "deploy.${branch}.timestamps")
if [ "${timestamps}" == "true" ]
then
# Set modification times to last-changed
for file in $(find ./ -type f)
do
# Get the date of the last commit
last=$(git log ${branch} --pretty=format:%ad --date=rfc -1 -- ${file})
# Set the modification time
touch -t $(date -d "${last}" +%Y%m%d%H%M.%S) ${file}
done
fi
# Copy worktree to destination
$RSYNC $opts "${scratch}/${branch}/" "${dest}"
status=$?
if [ "${status}" -ne "0" ]
then
echo "Error: rsync exited with exit code ${status}. Deploy may not have been successful. Please review the error log above."
else
echo "Deploy successful!"
fi
echo ""
done
##
## Cleanup
##
# Remove scratch dir
rm ${scratch} -rf
# Unset environment variables
unset GIT RSYNC TMP GIT_DIR scratch old new ref branch dest optstimestamps file
unset last