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 **[Welcome]***********************************************************
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 **[Dirty Tree]********************************************************
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 'Protected with quotes (e.g. "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 (e.g. 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 **[Bad origin]********************************************************
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 "**[Tracking branch]***************************************************"
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 **[Remote]************************************************************
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")
241 **********************************************************************
242 -- more -- Hit [RETURN] to continue, or C-c to abort.
248 **[Remote (cont)]*****************************************************
249 You _could_ use a git protocol URL (git://), but because the git
250 protocol has no authentication if you allow write access you are
251 allowing write access for anyone who has an internet connection. So
252 PLEASE DO NOT write to your remote via the git protocol.
254 Before we go ahead and add a remote to your repo, lets see if you have
256 **********************************************************************
257 Hit [RETURN] to continue, or C-c to abort.
260 REMOTES=($(git remote | grep -v origin))
262 echo "**[Remotes]***********************************************************"
263 echo " Currently configured remotes (possibly empty list)"
265 for (( i = 0; i <= ${#REMOTES}; i++ )); do
266 echo -en "\t"${i} -- ${REMOTES[${i}]}" at: "
267 echo $(git config remote.${REMOTES[${i}]}.url)
270 echo "**********************************************************************"
271 echo -n ' Enter the number that corresponds to your remote, or "x" for none: '
274 if [ "${index}" = "x" -o "${index}" = "" ]; then
276 echo -n 'Enter the "Fetch URL" (read-only access) to your remote: '
278 echo -n 'Enter the "Push URL" (write-access for you) to your remote: '
280 echo "And what would you like to call this remote? It MUST be a single"
281 echo -n 'word, and CANNOT be "origin": '
283 git remote add ${MYREMOTE_NAME} ${MYREMOTE_FETCH}
284 git remote set-url --push ${MYREMOTE_NAME} ${MYREMOTE_PUSH}
285 git config sxemacs.remote ${MYREMOTE_NAME}
288 URL=$(git config remote.${REMOTES[${index}]}.url)
289 while [ "${TYPE}" != "F" -a "${TYPE}" != "P" -a "${TYPE}" != "B" ]; do
291 echo -n " used for Fetch, Push, or Both? [F/P/B]: "
293 TYPE=$(echo ${TYPE}|tr 'fpb' 'FPB')
297 echo -n ${REMOTES[${index}]} '"Push URL" (write-access for you): '
299 git remote set-url --push ${REMOTES[${index}]} ${TYPEURL}
302 echo -n ${REMOTES[${index}]} '"Fetch URL" (read-only access): '
304 git remote set-url ${REMOTES[${index}]} ${TYPEURL}
305 git remote set-url --push ${REMOTES[${index}]} ${URL}
309 git config sxemacs.remote ${REMOTES[${index}]}
312 if [ -z "$(git config sxemacs.remote)" ]; then
315 **[Public repo]*******************************************************
316 The easiest, and quickest way to get your work and changes into the
317 main SXEmacs repository is if you have a publicly accessible remote
318 repo. Well, technically, it does not need to be publicly accessible,
319 it just needs to allow Steve read-only access. Nobody, except you,
320 will ever need to write to this repo.
321 **********************************************************************
323 echo -n " Do you have a remote repo like this set up? [Y/n]: "
325 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
328 echo "If you ever do set up a remote repo, please re-run this script."
335 for word in $(git config user.name); do
336 SXEINITIALS="${SXEINITIALS}$(echo ${word}|cut -c1)"
338 INTLS=${INITIALS:-${SXEINITIALS}}
339 TAGNAME=devkey.${INTLS}
341 git tag|grep -q ${TAGNAME} && TAGEXISTS=yes
342 if [ "${TAGEXISTS}" = "yes" ]; then
344 echo "**[Existing devkey]***************************************************"
345 echo "There is already a developer key tag using your initials..."
347 git show ${TAGNAME}|sed -n 2,5p
349 echo "**********************************************************************"
350 echo -n " Is it yours? [Y/n]: "
352 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
353 git config sxemacs.devkey $(git show-ref ${TAGNAME}|awk '{print $1;}')
355 echo -n "Setting developer key tagname to: "
356 echo "${TAGNAME}.$(git config user.signingKey)"
357 TAGNAME=${TAGNAME}.$(git config user.signingKey)
361 if [ -z "$(git config sxemacs.devkey)" ]; then
363 Developer Key -- $(git config user.name)
365 This is the GnuPG key used by $(git config user.name) <$(git config user.email)>
366 to sign commits, merges, and tags in this repository.
368 You may import this key into your GnuPG keyring with...
370 'git show ${TAGNAME} | gpg --import'
372 To verify signed objects in the repo, use the '--show-signature'
373 option with the git-log and git-show commands.
375 To verify this tag, use 'git tag -v ${TAGNAME}'
379 git tag -s ${TAGNAME} -m "${TAGMSG}" \
380 $(gpg --armor --export $(git config user.signingKey) |
381 git hash-object -w --stdin)
382 git config sxemacs.devkey $(git show-ref ${TAGNAME} |
385 # If something went wrong here we should probably bail out
386 if [ $? -gt 0 ]; then
387 echo 1>&2 'Something has gone horribly wrong while trying to add your devkey.'
388 echo 1>&2 'Please check that your local GnuPG settings are correct, and then'
389 echo 1>&2 'attempt to re-run this script.'
391 echo 1>&2 'If the problem persists, get in contact with us and we will do our'
392 echo 1>&2 'best to help you resolve it.'
396 echo "Your devkey tag has been created successfully."
398 echo -n "Can we now push ${TAGNAME} to $(git config sxemacs.remote)? [Y/n]: "
400 if [ "${RESP}" = "Y" -o "${RESP}" = "y" -o "${RESP}" = "" ]; then
401 git push $(git config sxemacs.remote) ${TAGNAME}
404 **[Devkey]************************************************************
405 Please let Steve know that your devkey is ready to be fetched into the
408 You can email Steve at steve@sxemacs.org, be sure to also include the
409 output from 'git config sxemacs.devkey', it will give Steve a way to
410 verify that the tag has not been tampered with.
411 **********************************************************************
412 Hit [RETURN] to continue, or C-c to abort.
421 # Make sure they've got Steve's key in their keyring. Safe to
422 # call even if the key exists in the keyring.
423 git tag|grep -q maintainer-pgp &&
424 git show maintainer-pgp|gpg --import --quiet
426 DEFKEY=$(grep '^default-key' ~/.gnupg/gpg.conf 2>/dev/null |
428 if [ -z "${DEFKEY}" ]; then
429 GUESS=$(gpg --list-keys $(git config user.email) |
430 awk '/^pub/ { split($2,k,"/"); print k[2] }')
431 SIGNKEY=${GUESS:-NOTSET}
436 if [ "${SIGNKEY}" = "NOTSET" ]; then
438 echo -n "Please enter the Key-ID of your default GnuPG key: "
440 [ -n "${RESP}" ] && git config user.signingKey ${RESP}
442 git config user.signingKey ${SIGNKEY}
445 git config --bool commit.gpgSign true
446 [ -n "$(git config sxemacs.devkey)" ] || set_tagblob
449 if ! type gpg 1>/dev/null ; then
452 **[No GnuPG]**********************************************************
453 WARNING: We could not find a gpg executable!
454 The GnuPG related setup in this script will be skipped.
456 We highly recommend that you have and use GnuPG (gpg) so that you can
457 both, verify the signed objects in the repository, and sign your own
460 Once you have GnuPG installed and set up please come back and re-run
462 **********************************************************************
463 Hit [RETURN] to continue, or C-c to abort.
466 elif [ -z "$(git config user.signingKey)" ]; then
470 # set_tagblog is called from set_keys but we may need to call it
471 # explicitly if user.signingKey was set prior to running this script.
472 [ -n "$(git config sxemacs.devkey)" ] || set_tagblob
474 ## Misc config (format, sendemail, etc)
477 [ -n "$(git config format.numbered)" ] ||
478 git config format.numbered auto
479 [ -n "$(git config format.to)" ] || git config format.to \
480 "SXEmacs Patches <sxemacs-patches@sxemacs.org>"
481 [ -n "$(git config format.subjectprefix)" ] ||
482 git config format.subjectprefix Patch
483 [ -n "$(git config format.headers)" ] || git config format.headers \
484 "X-Git-Repo: $(git config remote.$(git config sxemacs.remote).url)
485 X-Git-Branch: for-steve"
486 [ -n "$(git config sendemail.to)" ] || git config sendemail.to \
487 "SXEmacs Patches <sxemacs-patches@sxemacs.org>"
488 [ -n "$(git config sendemail.from)" ] || git config sendemail.from \
489 "$(git config user.name) <$(git config user.email)>"
492 echo "**[Format Summary]****************************************************"
493 echo " Here are the format and sendemail configs we just set."
495 echo " format.numbered --" $(git config format.numbered)
496 echo " format.to --" $(git config format.to)
497 echo " format.subjectprefix --" $(git config format.subjectprefix)
498 echo " format.headers --" $(git config format.headers)
499 echo " sendemail.to --" $(git config sendemail.to)
500 echo " sendemail.from --" $(git config sendemail.from)
502 echo "**********************************************************************"
503 echo -n " Hit [RETURN] to continue, or C-c to abort."
505 git config --bool sxemacs.formats true
507 BOOL=$(git config sxemacs.formats)
508 if [ "${BOOL}" != "true" ]; then
511 **[Formats]***********************************************************
512 We are going to set some format config values, but only if they are
513 not already set, so your existing ones are safe.
514 **********************************************************************
515 Hit [RETURN] to continue, or C-c to abort.
525 if [ -f ".git/hooks/post-commit" ]; then
526 if ! grep -q 'lines added by git-for-steve' .git/hooks/post-commit; then
527 cat>>.git/hooks/post-commit<<EOF
529 ### Begin - lines added by git-for-steve.sh
530 LOG=\$(git rev-parse --show-toplevel)/++log
531 [ -f \${LOG} ] && rm -f \${LOG}
532 ### End -- lines added by git-for-steve.sh
535 elif [ -f ".git/hooks/post-commit.sample" ]; then
536 cp .git/hooks/post-commit{.sample,}
537 sed -i /Nothing/d .git/hooks/post-commit
538 cat>>.git/hooks/post-commit<<EOF
540 ### Begin - lines added by git-for-steve.sh
541 LOG=\$(git rev-parse --show-toplevel)/++log
542 [ -f \${LOG} ] && rm -f \${LOG}
543 ### End -- lines added by git-for-steve.sh
546 cat>.git/hooks/post-commit<<EOF
548 ### Begin - lines added by git-for-steve.sh
549 LOG=\$(git rev-parse --show-toplevel)/++log
550 [ -f \${LOG} ] && rm -f \${LOG}
551 ### End -- lines added by git-for-steve.sh
553 chmod 755 .git/hooks/post-commit
557 HAVEHOOK=$(git config sxemacs.commithook)
558 if [ "${HAVEHOOK}" != "true" ]; then
561 **[Commit Hook]*******************************************************
562 Some of the SXEmacs developers use a variation of the
563 'add-change-log-entry' defun (C-x 4 a) for logging their changes
564 It creates a log file in the toplevel directory (called '++log') which
565 you can use with the '-F' switch of 'git commit'.
567 If you think that is something you would use (we hope you do), then we
568 can add a post-commit hook to your repo that automatically deletes
569 that log file after a successful commit.
570 **********************************************************************
572 echo -n " Shall we add the hook? [Y/n]: "
574 if [ "${HOOKME}" = "Y" -o "${HOOKME}" = "y" -o "${HOOKME}" = "" ]; then
576 git config --bool sxemacs.commithook true
584 echo "Which directory would you like to use as the output dir for"
585 echo -n "git format-patch, and send-email? [${TMP:-/tmp}]: "
587 GITTMP=${GITTMP:-${TMP:-/tmp}}
589 [ -n "$(git config alias.alias)" ] ||
590 git config alias.alias "config --get-regexp ^alias"
591 [ -n "$(git config alias.bi)" ] || git config alias.bi bisect
592 [ -n "$(git config alias.co)" ] || git config alias.co checkout
593 [ -n "$(git config alias.cob)" ] || git config alias.cob "checkout -b"
594 [ -n "$(git config alias.ci)" ] || git config alias.ci commit
595 [ -n "$(git config alias.cam)" ] || git config alias.cam "commit -sam"
596 [ -n "$(git config alias.sam)" ] || git config alias.sam "commit -sam"
598 BOOL=$(git config sxemacs.commithook)
599 if [ "${BOOL}" = "true" ]; then
600 [ -n "$(git config alias.cwl)" ] ||
601 git config alias.cwl \
602 '!git commit -sF $(git rev-parse --show-toplevel)/++log'
603 [ -n "$(git config alias.cawl)" ] ||
604 git config alias.cawl \
605 '!git commit -saF $(git rev-parse --show-toplevel)/++log'
608 [ -n "$(git config alias.rbi)" ] || git config alias.rbi "rebase -i"
609 [ -n "$(git config alias.prb)" ] || git config alias.prb "pull --rebase"
611 REMOTE=$(git config sxemacs.remote)
612 if [ -n "${REMOTE}" ]; then
613 [ -n "$(git config alias.pfs)" ] ||
614 git config alias.pfs "push ${REMOTE} for-steve"
617 [ -n "$(git config alias.fp)" ] || git config alias.fp \
618 "format-patch --minimal -o ${GITTMP} origin/master"
619 [ -n "$(git config alias.fpc)" ] || git config alias.fpc \
620 "format-patch --minimal --cover-letter -o ${GITTMP} origin/master"
621 [ -n "$(git config alias.sp)" ] || git config alias.sp \
622 "send-email ${GITTMP}"
623 [ -n "$(git config alias.spc)" ] || git config alias.spc \
624 "send-email --compose ${GITTMP}"
625 [ -n "$(git config alias.wb)" ] || git config alias.wb \
626 "rev-parse --abbrev-ref HEAD"
629 echo "**[Your Aliases]******************************************************"
630 echo " The following aliases are now available for use..."
634 echo "**********************************************************************"
635 echo -n " Hit [RETURN] to continue, or C-c to abort."
637 git config --bool sxemacs.aliases true
640 BOOL=$(git config sxemacs.aliases)
641 if [ "${BOOL}" != "true" ]; then
644 **[Aliases]***********************************************************
645 And finally, lets set a few aliases. We will only set them if they
646 have not already been set so all of your pre-existing aliases are
648 **********************************************************************
649 Hit [RETURN] to continue, or C-c to abort.
657 if [ ${LETSPOP} -eq 1 ]; then
658 # If we changed branches on them, go back.
659 if [ "${CURRENT_BRANCH}" != "$(git rev-parse --abbrev-ref HEAD)" ]; then
660 git checkout --quiet ${CURRENT_BRANCH}
662 git stash pop --quiet
665 ## All done, bar the shouting...
668 **[Thanks]************************************************************
669 | Thank you for taking the time to setup your repo so that you can |
670 | contribute back to the SXEmacs Project. We really appreciate all |
671 | that you do, no matter how small or insignificant you may think it |
672 | is, it all counts. |
674 | If you have not already done so, please take a few minutes now to |
675 | read through our policies and procedures manual, We call it the |
676 | "SPPM". From inside SXEmacs you can get to it via 'C-h C-i sppm', |
677 | or from the command line via 'info sppm'. |
679 | Also, now would be a good time for you to head over to |
680 | http://www.sxemacs.org/lists.html and subscribe to our mailing |
682 |--------------------------------------------------------------------|
683 | Thank you, and do drop into #sxemacs on freenode IRC for a chat |
684 | any time, especially if you need a hand with anything. |
685 **********************************************************************
689 ### git-for-steve.sh ends here.