1+ #! /usr/bin/env bash
2+ set -o errexit # abort if any command fails
3+ me=$( basename " $0 " )
4+
5+ help_message=" \
6+ Usage: $me [-c FILE] [<options>]
7+ Deploy generated files to a git branch.
8+
9+ Options:
10+
11+ -h, --help Show this help information.
12+ -v, --verbose Increase verbosity. Useful for debugging.
13+ -e, --allow-empty Allow deployment of an empty directory.
14+ -m, --message MESSAGE Specify the message used when committing on the
15+ deploy branch.
16+ -n, --no-hash Don't append the source commit's hash to the deploy
17+ commit's message.
18+ -c, --config-file PATH Override default & environment variables' values
19+ with those in set in the file at 'PATH'. Must be the
20+ first option specified.
21+
22+ Variables:
23+
24+ GIT_DEPLOY_DIR Folder path containing the files to deploy.
25+ GIT_DEPLOY_BRANCH Commit deployable files to this branch.
26+ GIT_DEPLOY_REPO Push the deploy branch to this repository.
27+
28+ These variables have default values defined in the script. The defaults can be
29+ overridden by environment variables. Any environment variables are overridden
30+ by values set in a '.env' file (if it exists), and in turn by those set in a
31+ file specified by the '--config-file' option."
32+
33+ bundle exec middleman build --clean
34+
35+ parse_args () {
36+ # Set args from a local environment file.
37+ if [ -e " .env" ]; then
38+ source .env
39+ fi
40+
41+ # Set args from file specified on the command-line.
42+ if [[ $1 = " -c" || $1 = " --config-file" ]]; then
43+ source " $2 "
44+ shift 2
45+ fi
46+
47+ # Parse arg flags
48+ # If something is exposed as an environment variable, set/overwrite it
49+ # here. Otherwise, set/overwrite the internal variable instead.
50+ while : ; do
51+ if [[ $1 = " -h" || $1 = " --help" ]]; then
52+ echo " $help_message "
53+ return 0
54+ elif [[ $1 = " -v" || $1 = " --verbose" ]]; then
55+ verbose=true
56+ shift
57+ elif [[ $1 = " -e" || $1 = " --allow-empty" ]]; then
58+ allow_empty=true
59+ shift
60+ elif [[ ( $1 = " -m" || $1 = " --message" ) && -n $2 ]]; then
61+ commit_message=$2
62+ shift 2
63+ elif [[ $1 = " -n" || $1 = " --no-hash" ]]; then
64+ GIT_DEPLOY_APPEND_HASH=false
65+ shift
66+ else
67+ break
68+ fi
69+ done
70+
71+ # Set internal option vars from the environment and arg flags. All internal
72+ # vars should be declared here, with sane defaults if applicable.
73+
74+ # Source directory & target branch.
75+ deploy_directory=build
76+ deploy_branch=gh-pages
77+
78+ # if no user identity is already set in the current git environment, use this:
79+ default_username=${GIT_DEPLOY_USERNAME:- deploy.sh}
80+ default_email=${GIT_DEPLOY_EMAIL:- }
81+
82+ # repository to deploy to. must be readable and writable.
83+ repo=origin
84+
85+ # append commit hash to the end of message by default
86+ append_hash=${GIT_DEPLOY_APPEND_HASH:- true}
87+ }
88+
89+ main () {
90+ parse_args " $@ "
91+
92+ enable_expanded_output
93+
94+ if ! git diff --exit-code --quiet --cached; then
95+ echo Aborting due to uncommitted changes in the index >&2
96+ return 1
97+ fi
98+
99+ commit_title=` git log -n 1 --format=" %s" HEAD`
100+ commit_hash=` git log -n 1 --format=" %H" HEAD`
101+
102+ # default commit message uses last title if a custom one is not supplied
103+ if [[ -z $commit_message ]]; then
104+ commit_message=" publish: $commit_title "
105+ fi
106+
107+ # append hash to commit message unless no hash flag was found
108+ if [ $append_hash = true ]; then
109+ commit_message=" $commit_message " $' \n\n ' " generated from commit $commit_hash "
110+ fi
111+
112+ previous_branch=` git rev-parse --abbrev-ref HEAD`
113+
114+ if [ ! -d " $deploy_directory " ]; then
115+ echo " Deploy directory '$deploy_directory ' does not exist. Aborting." >&2
116+ return 1
117+ fi
118+
119+ # must use short form of flag in ls for compatibility with OS X and BSD
120+ if [[ -z ` ls -A " $deploy_directory " 2> /dev/null` && -z $allow_empty ]]; then
121+ echo " Deploy directory '$deploy_directory ' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2
122+ return 1
123+ fi
124+
125+ if git ls-remote --exit-code $repo " refs/heads/$deploy_branch " ; then
126+ # deploy_branch exists in $repo; make sure we have the latest version
127+
128+ disable_expanded_output
129+ git fetch --force $repo $deploy_branch :$deploy_branch
130+ enable_expanded_output
131+ fi
132+
133+ # check if deploy_branch exists locally
134+ if git show-ref --verify --quiet " refs/heads/$deploy_branch "
135+ then incremental_deploy
136+ else initial_deploy
137+ fi
138+
139+ restore_head
140+ }
141+
142+ initial_deploy () {
143+ git --work-tree " $deploy_directory " checkout --orphan $deploy_branch
144+ git --work-tree " $deploy_directory " add --all
145+ commit+push
146+ }
147+
148+ incremental_deploy () {
149+ # make deploy_branch the current branch
150+ git symbolic-ref HEAD refs/heads/$deploy_branch
151+ # put the previously committed contents of deploy_branch into the index
152+ git --work-tree " $deploy_directory " reset --mixed --quiet
153+ git --work-tree " $deploy_directory " add --all
154+
155+ set +o errexit
156+ diff=$( git --work-tree " $deploy_directory " diff --exit-code --quiet HEAD --) $?
157+ set -o errexit
158+ case $diff in
159+ 0) echo No changes to files in $deploy_directory . Skipping commit.;;
160+ 1) commit+push;;
161+ * )
162+ echo git diff exited with code $diff . Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2
163+ return $diff
164+ ;;
165+ esac
166+ }
167+
168+ commit+push () {
169+ set_user_id
170+ git --work-tree " $deploy_directory " commit -m " $commit_message "
171+
172+ disable_expanded_output
173+ # --quiet is important here to avoid outputting the repo URL, which may contain a secret token
174+ git push --quiet $repo $deploy_branch
175+ enable_expanded_output
176+ }
177+
178+ # echo expanded commands as they are executed (for debugging)
179+ enable_expanded_output () {
180+ if [ $verbose ]; then
181+ set -o xtrace
182+ set +o verbose
183+ fi
184+ }
185+
186+ # this is used to avoid outputting the repo URL, which may contain a secret token
187+ disable_expanded_output () {
188+ if [ $verbose ]; then
189+ set +o xtrace
190+ set -o verbose
191+ fi
192+ }
193+
194+ set_user_id () {
195+ if [[ -z ` git config user.name` ]]; then
196+ git config user.name " $default_username "
197+ fi
198+ if [[ -z ` git config user.email` ]]; then
199+ git config user.email " $default_email "
200+ fi
201+ }
202+
203+ restore_head () {
204+ if [[ $previous_branch = " HEAD" ]]; then
205+ # we weren't on any branch before, so just set HEAD back to the commit it was on
206+ git update-ref --no-deref HEAD $commit_hash $deploy_branch
207+ else
208+ git symbolic-ref HEAD refs/heads/$previous_branch
209+ fi
210+
211+ git reset --mixed
212+ }
213+
214+ filter () {
215+ sed -e " s|$repo |\$ repo|g"
216+ }
217+
218+ sanitize () {
219+ " $@ " 2> >( filter 1>&2 ) | filter
220+ }
221+
222+ [[ $1 = --source-only ]] || main " $@ "
0 commit comments