3 # A script to setup your git area to contribute back to SXEmacs
5 # Copyright (C) 2008 Nelson Ferreira
6 # Copyright (C) 2015 Steve Youngs
8 # This program is free software; you can redistribute it and/or modify it
9 # under a BSD-like licence.
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions are met:
13 # Redistributions of source code must retain the above copyright notice, this
14 # list of conditions and the following disclaimer.
15 # Redistributions in binary form must reproduce the above copyright notice,
16 # this list of conditions and the following disclaimer in the documentation
17 # and/or other materials provided with the distribution.
18 # Neither the name of the Technical University of Berlin nor the names of its
19 # contributors may be used to endorse or promote products derived from this
20 # software without specific prior written permission.
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
37 ## This script sets up your SXEmacs git WD so that contributing
38 ## back to the SXEmacs project is as easy as possible, in the way
39 ## that the maintainers like best. :-)
41 ## Much care has been taken to NOT overwrite your current settings.
42 ## Most times, a setting will only be set if it is not already set,
43 ## and you will be prompted before any changes are made, giving you
44 ## the option to bail out.
46 ## Before the script does anything it checks to make sure you are
47 ## running it in a SXEmacs source tree (bails out, if not).
48 ## And if you have a dirty WD (uncommitted changes) the script will
49 ## stash them first, just to be safe (they're restored at the end).
51 ## The stuff this script looks at and might sets/changes:
53 ## user.name, user.email, user.signingKey, commit.gpgSign,
54 ## format.numbered, format.to, format.subjectprefix,
55 ## format.headers, sendmail.to, sendmail.from
57 ## It also ensures that origin points to the right place
58 ## (http://git.sxemacs.org/sxemacs), optionally makes sure your
59 ## remote is set up correctly, that you have a "for-steve" tracking
60 ## branch, and adds a devkey.$INITIALS tag containing your public
61 ## GnuPG key if available, which can be pushed to your remote.
63 ## Oh, and it adds a swag of nice aliases.
67 **********************************************************************
68 | Hello, and welcome to the SXEmacs Team |
70 | This script will help guide you through setting up your personal |
71 | SXEmacs git repo in a way that will make your life as a developer, |
72 | and contributor, as easy as possible. |
74 | We just make sure a few basics are set like name, email, the right |
75 | tracking branch, remotes, etc, and add a few nice aliases and |
76 | config options. You will be prompted if we need to make any |
77 | changes to your config, and you can bail out at any time with C-c. |
78 |--------------------------------------------------------------------|
79 | I hope you get immense fun and satisfaction from hacking SXEmacs |
80 | Steve Youngs <steve@sxemacs.org> "SteveYoungs" on IRC |
81 **********************************************************************
82 Hit [RETURN] to continue, or C-c to abort.
86 # Work in the toplevel dir just to be on the safe side
87 pushd $(git rev-parse --show-toplevel) 1>/dev/null ||
88 ( echo 1>&2 "Please run this script from _inside_ your SXEmacs repo."
91 # Lets not mess about in anything that isn't a SXEmacs repo
92 if [ "$(git show-ref v22.1.13 2>/dev/null|cut -c-8)" != "5ff9eebe" ]; then
93 echo 1>&2 "This is NOT a SXEmacs repo, bailing out!"
98 # Save the current branch name in case we move about
99 CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
106 **********************************************************************
107 Your working directory contains changes that have not been committed
108 yet. Under certain conditions this script may do a couple of branch
109 jumps, so we will play it safe and store your changes out of the way
110 with 'git stash'. We will 'pop' them back again when we are all done
112 **********************************************************************
113 Hit [RETURN] to continue, or C-c to abort.
116 git stash save --all --quiet "git-for-steve.sh safety stash"
120 DIRTY=$(git status -u --ignored --porcelain -z)
121 [ -n "${DIRTY}" ] && clear_wd
127 echo "Please enter your name as you would like it to appear in the logs"
128 echo -n "Take care to guard against shell expansion (\"John Doe\"): "
134 [ $USER ] && NAMEGUESS=$(getent passwd $USER|cut -d: -f5)
136 if [ -n "${NAMEGUESS}" ]; then
138 echo "Git needs to know your name (for commit logs, etc)."
139 echo -n "Can we use \"${NAMEGUESS}\"? [Y/n]: "
141 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
150 git config user.name "${NAME}"
152 [ -n "$(git config user.name)" ] || set_name
158 echo "Git needs to know your email address (for commit logs, etc)."
159 echo -n "Please enter your email address (eg john@doe.com): "
161 git config user.email ${EMAIL}
163 [ -n "$(git config user.email)" ] || set_email
165 ## Tracking branch "for-steve"
166 # Make sure origin points to http://git.sxemacs.org/sxemacs
167 CHECK_ORIGIN=${CHECK_ORIGIN:-true}
168 if [ "${CHECK_ORIGIN}" != "false" ]; then
169 ORIGIN_URL=$(git config remote.origin.url)
170 if [ "${ORIGIN_URL}" != "http://git.sxemacs.org/sxemacs" ]; then
173 **********************************************************************
174 WARNING: origin URL is WRONG.
176 It is currently set to: ${ORIGIN_URL}
177 But it SHOULD be set to: http://git.sxemacs.org/sxemacs
179 It you are absolutely 110% sure that your origin is correct, abort now
180 with C-c, and re-run this script with the environment variable,
181 "CHECK_ORIGIN" set explicitly to the string: "false". Otherwise we
182 are going to reset it for you.
183 **********************************************************************
184 Hit [RETURN] to continue, or C-c to abort.
187 git remote set-url origin http://git.sxemacs.org/sxemacs
194 echo "**********************************************************************"
195 echo "Setting up a \"for-steve\" branch to track origin/master."
197 echo "This is the branch that you will merge your work into once it is"
198 echo "ready for Steve to pull into his repo."
199 echo "**********************************************************************"
200 echo -n " Hit [RETURN] to continue, or C-c to abort."
202 # Does it make a difference from where we do this from? Lets jump
203 # into master if we're not there already, just to be on the safe
205 [ "${CURRENT_BRANCH}" != "master" ] && git checkout --quiet master
206 git branch --track for-steve origin/master
207 # Offer to leave them in for-steve, but only if we didn't stash
208 if [ ${LETSPOP} -eq 0 ]; then
210 echo -n "Switch to the \"for-steve\" branch when this script exits? [Y/n]: "
212 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
213 git checkout --quiet for-steve
217 git branch | grep -q for-steve || set_branch
225 **********************************************************************
226 You need to have a remote repository set up for you to push your
227 changes to. Steve will need read-only access so he can fetch your
228 changes into his repo. You can name this repo anything you like,
229 just as long as it is a single word, and that word is not \"origin\".
231 A remote repo can have a "Fetch URL", and a "Push URL". The
232 former (Fetch URL) is the URL from which people would clone, pull,
233 fetch from. And the latter (Push URL) is the URL you would use to
236 The Push URL to your remote needs to be writable for you, here are a
237 couple of examples...
239 ssh://user@example.com/~/path/to/repo (using ssh)
240 https://user:pass@example.com/path/to/repo (using \"smart http\")
242 You _could_ use a git protocol URL (git://), but because the git
243 protocol has no authentication if you allow write access you are
244 allowing write access for anyone who has an internet connection. So
245 PLEASE DO NOT write to your remote via the git protocol.
247 Before we go ahead and add a remote to your repo, lets see if you have
249 **********************************************************************
250 Hit [RETURN] to continue, or C-c to abort.
253 REMOTES=("$(git remote | grep -v origin)")
255 echo "**********************************************************************"
256 echo " Currently configured remotes (possibly empty list)"
258 for (( i = 1; i <= ${#REMOTES}; i++ )); do
259 echo -n "\t"${i} -- ${REMOTES[${i}]}" at: "
260 echo $(git config remote.${REMOTES[${i}]}.url)
263 echo "**********************************************************************"
264 echo -n " Enter the number that corresponds to your remote, or \"x\" for none: "
267 if [ "${index}" = "x" -o "${index}" = "" ]; then
269 echo -n "Enter the \"Fetch URL\" (read-only access) to your remote: "
271 echo -n "Enter the \"Push URL\" (write-access for you) to your remote: "
273 echo "And what would you like to call this remote? It MUST be a single "
274 echo -n "word, and CANNOT be \"origin\": "
276 git remote add ${MYREMOTE_NAME} ${MYREMOTE_FETCH}
277 git remote set-url --push ${MYREMOTE_NAME} ${MYREMOTE_PUSH}
278 git config sxemacs.remote ${MYREMOTE_NAME}
281 URL=$(git config remote.${REMOTES[${index}]}.url)
282 while [ "${TYPE}" != "F" -a "${TYPE}" != "P" -a "${TYPE}" != "B" ]; do
284 echo -n " used for Fetch, Push, or Both? [F/P/B]: "
286 TYPE=$(echo ${TYPE}|tr 'fpb' 'FPB')
290 echo -n "${REMOTES[${index}]} \"Push URL\" (write-access for you): "
292 git remote set-url --push ${REMOTES[${index}]} ${TYPEURL}
295 echo -n "${REMOTES[${index}]} \"Fetch URL\" (read-only access): "
297 git remote set-url ${REMOTES[${index}]} ${TYPEURL}
298 git remote set-url --push ${REMOTES[${index}]} ${URL}
302 git config sxemacs.remote ${REMOTES[${index}]}
305 if [ -z "$(git config sxemacs.remote)" ]; then
308 **********************************************************************
309 The easiest, and quickest way to get your work and changes into the
310 main SXEmacs repository is if you have a publicly accessible remote
311 repo. Well, technically, it does not need to be publicly accessible,
312 it just needs to allow Steve read-only access. Nobody, except you,
313 will ever need to write to this repo.
314 **********************************************************************
316 echo -n " Do you have a remote repo like this set up? [Y/n]:"
318 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
321 echo "If you ever do set up a remote repo, please re-run this script."
328 for word in $(git config user.name); do
329 SXEINITIALS="${SXEINITIALS}$(echo ${word}|cut -c1)"
331 INTLS=${INITIALS:-${SXEINITIALS}}
332 TAGNAME=devkey.${INTLS}
334 git tag|grep -q ${TAGNAME} && TAGEXISTS=yes
335 if [ "${TAGEXISTS}" = "yes" ]; then
336 echo "There is already a developer key tag using your initials..."
338 git show ${TAGNAME}|sed -n 2,5p
340 echo -n "Is it yours? [Y/n]: "
342 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
343 git config sxemacs.devkey $(git show-ref ${TAGNAME}|awk '{print $1;}')
345 echo -n "Setting developer key tagname to: "
346 echo "${TAGNAME}.$(git config user.signingKey)"
347 TAGNAME=${TAGNAME}.$(git config user.signingKey)
351 if [ -z "$(git config sxemacs.devkey)" ]; then
353 Developer Key -- $(git config user.name)
355 This is the GnuPG key used by $(git config user.name) <$(git config user.email)>
356 to sign commits, merges, and tags in this repository.
358 You may import this key into your GnuPG keyring with...
360 'git show ${TAGNAME} | gpg --import'
362 To verify signed objects in the repo, use the '--show-signature'
363 option with the git-log and git-show commands.
367 git tag -s ${TAGNAME} -m "${TAGMSG}" \
368 $(gpg --armor --export $(git config user.signingKey) |
369 git hash-object -w --stdin)
370 git config sxemacs.devkey $(git show-ref ${TAGNAME} |
374 echo "Your devkey tag has been created successfully."
375 echo -n "Can we now push ${TAGNAME} to $(git config sxemacs.remote)? [Y/n]: "
377 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
378 git push $(git config sxemacs.remote) ${TAGNAME}
381 **********************************************************************
382 Please let Steve know that your devkey is ready to be fetched into the
385 You can email Steve at steve@sxemacs.org, be sure to also include the
386 output from 'git config sxemacs.devkey', it will give Steve a way to
387 verify that the tag has not been tampered with.
388 **********************************************************************
389 Hit [RETURN] to continue, or C-c to abort.
398 # Make sure they've got Steve's key in their keyring. Safe to
399 # call even if the key exists in the keyring.
400 git tag|grep -q maintainer-pgp &&
401 git show maintainer-pgp|gpg --import --quiet
403 DEFKEY=$(grep default-key ~/.gnupg/gpg.conf 2>/dev/null |
405 if [ -z "${DEFKEY}" ]; then
406 GUESS=$(gpg --list-keys $(git config user.email) |
407 awk '/^pub/ { split($2,k,"/"); print k[2] }')
408 SIGNKEY=${GUESS:-NOTSET}
413 if [ "${SIGNKEY}" = "NOTSET" ]; then
415 echo -n "Please enter the Key-ID of your default GnuPG key: "
417 [ -n "${RESP}" ] && git config user.signingKey ${RESP}
419 git config user.signingKey ${SIGNKEY}
422 git config --bool commit.gpgSign true
423 [ -n "$(git config sxemacs.devkey)" ] || set_tagblob
426 if ! type gpg 1>/dev/null ; then
429 **********************************************************************
430 WARNING: We could not find a gpg executable!
431 The GnuPG related setup in this script will be skipped.
433 We highly recommend that you have and use GnuPG (gpg) so that you can
434 both, verify the signed objects in the repository, and sign your own
437 Once you have GnuPG installed and set up please come back and re-run
439 **********************************************************************
440 Hit [RETURN] to continue, or C-c to abort.
443 elif [ -z "$(git config user.signingKey)" ]; then
447 # set_tagblog is called from set_keys but we may need to call it
448 # explicitly if user.signingKey was set prior to running this script.
449 [ -n "$(git config sxemacs.devkey)" ] || set_tagblob
451 ## Misc config (format, sendemail, etc)
454 [ -n "$(git config format.numbered)" ] ||
455 git config format.numbered auto
456 [ -n "$(git config format.to)" ] || git config format.to \
457 "SXEmacs Patches <sxemacs-patches@sxemacs.org>"
458 [ -n "$(git config format.subjectprefix)" ] ||
459 git config format.subjectprefix Patch
460 git config format.headers || git config format.headers \
461 "X-Git-Repo: $(git config remote.$(git config sxemacs.remote).url)
462 X-Git-Branch: for-steve"
463 [ -n "$(git config sendemail.to)" ] || git config sendemail.to \
464 "SXEmacs Patches <sxemacs-patches@sxemacs.org>"
465 [ -n "$(git config sendemail.from)" ] || git config sendemail.from \
466 "$(git config user.name) <$(git config user.email)>"
469 echo "**********************************************************************"
470 echo " Here are the format and sendemail configs we just set."
472 echo " format.numbered --" $(git config format.numbered)
473 echo " format.to --" $(git config format.to)
474 echo " format.subjectprefix --" $(git config format.subjectprefix)
475 echo " format.headers --" $(git config format.headers)
476 echo " sendemail.to --" $(git config sendemail.to)
477 echo " sendemail.from --" $(git config sendemail.from)
479 echo "**********************************************************************"
480 echo -n " Hit [RETURN] to continue, or C-c to abort."
482 git config --bool sxemacs.formats true
484 BOOL=$(git config sxemacs.formats)
485 if [ "${BOOL}" != "true" ]; then
487 echo "We're going to set some format config values, but only if they aren't"
488 echo "already set, so your existing ones are safe."
496 if [ -f ".git/hooks/post-commit" ]; then
497 cat>>.git/hooks/post-commit<<EOF
499 ### Begin - lines added by git-for-steve.sh
500 LOG=\$(git rev-parse --show-toplevel)/++log
501 [ -f \${LOG} ] && rm -f \${LOG}
502 ### End -- lines added by git-for-steve.sh
504 elif [ -f ".git/hooks/post-commit.sample" ]; then
505 cat>>.git/hooks/post-commit.sample<<EOF
507 ### Begin - lines added by git-for-steve.sh
508 LOG=\$(git rev-parse --show-toplevel)/++log
509 [ -f \${LOG} ] && rm -f \${LOG}
510 ### End -- lines added by git-for-steve.sh
512 sed -i /Nothing/d .git/hooks/post-commit.sample
513 mv .git/hooks/post-commit{.sample,}
515 cat>.git/hooks/post-commit<<EOF
517 ### Begin - lines added by git-for-steve.sh
518 LOG=\$(git rev-parse --show-toplevel)/++log
519 [ -f \${LOG} ] && rm -f \${LOG}
520 ### End -- lines added by git-for-steve.sh
522 chmod 755 .git/hooks/post-commit
526 HAVEHOOK=$(git config sxemacs.commithook)
527 if [ "${HAVEHOOK}" != "true" ]; then
530 **********************************************************************
531 Some of the SXEmacs developers use a variation of the
532 #'add-change-log-entry defun (C-x 4 a) for logging their changes
533 It creates a log file in the toplevel directory (called '++log') which
534 you can use with the '-F' switch of 'git commit'.
536 If you think that is something you would use (we hope you do), then we
537 can add a post-commit hook to your repo that automatically deletes
538 that log file after a successful commit.
539 **********************************************************************
541 echo -n " Shall we add the hook? [Y/n]: "
543 if [ "${HOOKME}" = "Y" -o "${HOOKME}" = "y" -o "${HOOKME}" = "" ]; then
545 git config --bool sxemacs.commithook true
553 echo "Which directory would you like to use as the output dir for"
554 echo -n "git format-patch, and send-email? [${TMP:-/tmp}]: "
556 GITTMP=${GITTMP:-${TMP:-/tmp}}
558 [ -n "$(git config alias.alias)" ] ||
559 git config alias.alias "config --get-regexp ^alias"
560 [ -n "$(git config alias.bi)" ] || git config alias.bi bisect
561 [ -n "$(git config alias.co)" ] || git config alias.co checkout
562 [ -n "$(git config alias.cob)" ] || git config alias.cob "checkout -b"
563 [ -n "$(git config alias.ci)" ] || git config alias.ci commit
564 [ -n "$(git config alias.cam)" ] || git config alias.cam "commit -sam"
566 BOOL=$(git config sxemacs.commithook)
567 if [ "${BOOL}" = "true" ]; then
568 [ -n "$(git config alias.cwl)" ] ||
569 git config alias.cwl \
570 '!git commit -sF $(git rev-parse --show-toplevel)/++log'
571 [ -n "$(git config alias.cawl)" ] ||
572 git config alias.cawl \
573 '!git commit -saF $(git rev-parse --show-toplevel)/++log'
576 [ -n "$(git config alias.rbi)" ] || git config alias.rbi "rebase -i"
577 [ -n "$(git config alias.prb)" ] || git config alias.prb "pull --rebase"
578 [ -n "$(git config alias.pfs)" ] ||
579 git config alias.pfs "push $(git config sxemacs.remote) for-steve"
580 [ -n "$(git config alias.fp)" ] || git config alias.fp \
581 "format-patch --minimal -o ${GITTMP} origin/master"
582 [ -n "$(git config alias.fpc)" ] || git config alias.fpc \
583 "format-patch --minimal --cover-letter -o ${GITTMP} origin/master"
584 [ -n "$(git config alias.sp)" ] || git config alias.sp \
585 "send-email ${GITTMP}"
586 [ -n "$(git config alias.spc)" ] || git config alias.spc \
587 "send-email --compose ${GITTMP}"
588 [ -n "$(git config alias.wb" ] || git config alias.wb \
589 "rev-parse --abbrev-ref HEAD"
592 echo "**********************************************************************"
593 echo " The following aliases are now available for use..."
597 echo "**********************************************************************"
598 echo -n " Hit [RETURN] to continue, or C-c to abort."
600 git config --bool sxemacs.aliases true
603 BOOL=$(git config sxemacs.aliases)
604 if [ "${BOOL}" != "true" ]; then
607 **********************************************************************
608 And finally, lets set a few aliases. We will only set them if they
609 have not already been set so all of your pre-existing aliases are
611 **********************************************************************
612 Hit [RETURN] to continue, or C-c to abort.
620 if [ ${LETSPOP} -eq 1 ]; then
621 # If we changed branches on them, go back.
622 if [ "${CURRENT_BRANCH}" != "$(git rev-parse --abbrev-ref HEAD)" ]; then
623 git checkout --quiet ${CURRENT_BRANCH}
625 git stash pop --quiet
628 ## All done, bar the shouting...
631 **********************************************************************
632 | Thank you for taking the time to setup your repo so that you can |
633 | contribute back to the SXEmacs Project. We really appreciate all |
634 | that you do, no matter how small or insignificant you may think it |
635 | is, it all counts. |
637 | If you have not already done so, please take a few minutes now to |
638 | read through our policies and procedures manual, We call it the |
639 | "SPPM". From inside SXEmacs you can get to it via 'C-h C-i sppm', |
640 | or from the command line via 'info sppm'. |
642 | Also, now would be a good time for you to head over to |
643 | http://www.sxemacs.org/lists.html and subscribe to our mailing |
645 |--------------------------------------------------------------------|
646 | Thank you, and do drop into #sxemacs on freenode IRC for a chat |
647 | any time, especially if you need a hand with anything. |
648 **********************************************************************
652 ### git-for-steve.sh ends here.