Advertisement
Guest User

Untitled

a guest
May 24th, 2017
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.54 KB | None | 0 0
  1. #!/bin/sh
  2.  
  3. # This script will:
  4. # - list submodules inside a parent repository supplied on $1
  5. # - check whether they are marked as changed while ignoring dirty files
  6. # - verify that there are no other staged changes before proceeding
  7. # - send emails to the local user at the local hostname (-f) using the local
  8. # user also as the sender. It will send emails for: commit error,
  9. # staged changes existing, and success. It will not send emails for other
  10. # program errors. If you use this script from cron, then all other error
  11. # output will be sent to you by cron.
  12.  
  13. # - the program will output some progress information on stdout; but will not
  14. # do so if the script is not run interactively.
  15.  
  16. # This script is verified to work with: bash and busybox ash.
  17.  
  18. # This program is called:
  19.  
  20.  
  21.  
  22. # automatic parent commits
  23.  
  24. unset int
  25.  
  26. [ -t 0 ] && int=yes
  27.  
  28. username=$(id -nu)
  29. hostname=$(hostname -f)
  30. email="$username@$hostname"
  31.  
  32. medium_minus_date="commit %H%nAuthor: %an <%ae>%n%n%w(0,4,4)%B"
  33.  
  34. [ -z "$1" ] && {
  35. echo "Give a git that has submodules as parameter" >&2
  36. exit 255
  37. }
  38.  
  39. cd "$1" && {
  40. repository=$(readlink -f "$(pwd)")
  41. } || {
  42. echo "Directory $repository does not exist or is not accessable" >&2
  43. exit 1
  44. }
  45.  
  46. [ -d .git ] || {
  47. echo "This is not a git repository: $repository" >&2
  48. exit 1
  49. }
  50.  
  51. # get-url was not implemented in older git versions
  52.  
  53. repo_name=$(git remote show -n origin | grep "Fetch URL" | sed "s@.*/\(.*\).git@\1@")
  54.  
  55. # We shall first get the list of submodules using:
  56. submodules=$(git submodule -q foreach 'echo $path')
  57.  
  58. [ -t 0 ] && { echo "List of submodules:"; echo "$submodules" | sed "s/.*/ &/"; echo; }
  59.  
  60. # Then we shall hopefully find the list of modified submodules using:
  61.  
  62. out=$(git status --porcelain --ignore-submodules=dirty) || {
  63. echo "Git status gave an error. Is this a git repository?" >&2
  64. exit 1
  65. }
  66.  
  67. list=$(printf "%s\n" "$out" | sed "s/.*/#&/" | while read a; do
  68. # Spaces as meaningful characters is not easy in shell code.
  69. c=$(echo "$a" | sed "s/#.. //")
  70. b=${a% $c}
  71. b=${b#\#}
  72. # This first part filters on subrepository names.
  73. if echo "$submodules" | grep -q "^$c$"; then
  74. printf "%-2s %s\n" "$b" "$c"
  75. fi
  76. # Then we filter on an "M" in the second column.
  77. done | grep "^.M" | sed "s/.. //" )
  78.  
  79. [ -t 0 ] && { echo "Submodules that are modified:"; echo "$list" | sed "s/.*/ &/"; echo; }
  80.  
  81. # Then we shall go on.
  82.  
  83. # I used to use the human readable version but it didn't tell me whether something was a submodule
  84. # when it already had the submodule staged for commit....:
  85.  
  86. # out=$(echo "$out" | grep "^# modified:.*(.*new commits.*)$" | sed "s/.*: *\([^ ].*\) (.*)$/\1/")
  87.  
  88. [ -z "$list" ] || {
  89. # Now we check whether the index does not contain staged changes:
  90. git status --porcelain --ignore-submodules=dirty | grep -q "^[MADRC]." && {
  91.  
  92. # And we send an email if they are staged:
  93. echo "From: $email
  94. To: $email
  95. Subject: Repo $repo_name already contains staged changes
  96.  
  97. There are sub-modules that have changes to be committed to the parent repo $repo_name but the index is not clean; there are staged changes:
  98.  
  99. $(git status --ignore-submodules=dirty | sed -n -e "/^# Changes to be committed/,/^# [^ ]/p" | sed '$d')" | /usr/sbin/sendmail -t
  100. [ -t 0 ] && echo "Sent staged changes preventing operation mail to $email"
  101. # And we exit. Stash -u would take care of those staged things but unfortunately I don't think it is very
  102. # safe to do so.
  103.  
  104. # I can't tell if I can ever lock a repository and files might also be open in the working tree that then
  105. # gets swapped around back and forth.
  106.  
  107. # I would have to unstage things and then restage them back. That's easy enough but still runs the potential
  108. # risk of interfering with a user.
  109.  
  110. # What I do needs to be atomic etc.
  111.  
  112. exit 1
  113. }
  114.  
  115. # Let's first determine the date to use for our commit message:
  116.  
  117. # The date is slightly influenced by the locale (the %a term means like Wed)
  118. # This string results in "Wed 31-10-2017 22:00". I didn't like my own locale
  119. # (en_US becomes 10/31/2017 but nl_NL becomes 31-10-17 and locales also change dots into commas.
  120. # Very annoying. I hate that so much. Calculators don't take . input, only , input. So the thing
  121. # you're used to, typing 10.23 as a decimal number, suddenly doesn't work and the number becomes
  122. # 1023. That person who invented that deserves a proper hanging.
  123.  
  124. date=$(date "+%a %d-%m-%Y %H:%M")
  125.  
  126. # Anyway you can always change this around to your preference.
  127.  
  128. # The list is now supplied with a here doc down below so that we can save the variables inside.
  129.  
  130. unset error_repos errmsg changelist
  131.  
  132. while read a; do
  133. git add "$a"
  134.  
  135. currerr=$(git commit -m "Hourly repository update for submodule $a at $date" 2>&1 > /dev/null) && {
  136. changelist="$changelist$a
  137. "
  138. [ $int ] && echo "Successfully committed $a."
  139. true
  140. } || {
  141. error=$?
  142. error_repos="$error_repos$a
  143. "
  144. errmsg="$errmsg$currerr
  145. "
  146. [ $int ] && echo "Failed to commit $a."
  147. git reset -q "$a"
  148. }
  149. done << EOF
  150. $list
  151. EOF
  152.  
  153. # Remove the extra \n I gave it:
  154. changelist=${changelist%?}
  155. error_repos=${error_repos%?}
  156.  
  157. # If there were errors at committing they are now collected in this error repo list.
  158. [ -n "$error_repos" ] && {
  159.  
  160. # start and error commits:
  161. first="From: $email
  162. To: $email
  163. Subject: Commits contain errors @ auto-update for $repo_name
  164.  
  165. Commits that gave errors:
  166. $(echo -n "$error_repos" | sed "s/.*/- &/")"
  167.  
  168. # any successful commits
  169. if [ -n "$changelist" ]; then
  170. first="$first
  171.  
  172. Commits that succeeded:
  173. $(echo -n "$changelist" | sed "s/.*/- &/")"
  174. fi
  175.  
  176. # the full message
  177. first="$first
  178.  
  179. Error messages:
  180. $(echo -n "$errmsg" | sed "s/.*/ &/")"
  181.  
  182. echo "$first" | /usr/sbin/sendmail -t
  183. [ -t 0 ] && echo "Sent error mail to $email"
  184. exit 1
  185.  
  186. }
  187.  
  188. # If not, then we proceed with a regular commit message as there MUST be successful commits now:
  189.  
  190. count=$(echo "$changelist" | wc -l)
  191.  
  192. if [ "$count" -gt 1 ]; then m=s; fi
  193.  
  194. if [ "$count" -eq 1 ]; then
  195. echo "From: $email
  196. To: $email
  197. Subject: Updated parent for sub-module $repo_name/$changelist
  198.  
  199. The repository $repo_name had its reference to submodule $changelist updated to its latest commit:
  200.  
  201. $(cd $changelist; git log -1 --format="$medium_minus_date" | sed "s/.*/ &/")" | /usr/sbin/sendmail -t
  202. else
  203. { echo "From: $email
  204. To: $email
  205. Subject: Updated parent $repo_name for $count submodule repositories
  206.  
  207.  
  208. "
  209. while read r; do
  210. echo "The repository $repo_name had its reference to submodule $r updated to its latest commit:
  211.  
  212. $(cd $r; git log -1 --format="$medium_minus_date" | sed "s/.*/ &/")
  213. "
  214. done << EOF
  215. $changelist
  216. EOF
  217. } | /usr/sbin/sendmail -t
  218. fi
  219.  
  220. [ -t 0 ] && echo "Sent commit mail to $email"
  221. true
  222. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement