diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-27 06:42:36 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-27 07:04:54 +0200 |
commit | 31cb850c04873e29ad1ff5a5d5255283827907b2 (patch) | |
tree | 59469c23704ee637f6c23982c2cf68168d42408d /update | |
parent | 01ee7236a462b07b7e45bb4800920ba1bef88c65 (diff) |
Diffstat (limited to 'update')
-rwxr-xr-x | update | 164 |
1 files changed, 164 insertions, 0 deletions
@@ -0,0 +1,164 @@ +#! /usr/bin/env bash + +# Commit and push an update to an existing note. +# +# -c +# Commit only, don't push. +# +usage="usage: $0 [-c]" + +owd=`pwd` +trap "{ cd $owd; exit 1; }" ERR +set -o errtrace # Trap in functions. + +function info () { echo "$*" 1>&2; } +function error () { info "$*"; exit 1; } + +push="y" + +while [ $# -gt 0 ]; do + case $1 in + -c) + push="n" + shift + ;; + *) + error "$usage" + ;; + esac +done + +if git status --porcelain | grep -q '^M '; then + error "error: repository already has staged changes" +fi + +# @@ We could probably handle the case where extra files are added to the +# note. We just need to make sure they are not changes to other notes. +# +if git status --porcelain | grep -q '^?? '; then + error "error: repository has untracked files" +fi + +modified="$(git status --porcelain | sed -n -e 's/^ M \(.*\)/\1/p')" + +mc="$(echo "$modified" | wc -w)" + +if [ "$mc" -eq 0 ]; then + error "error: nothing modified" +fi + +if [ "$mc" -gt 1 ]; then + error "error: multiple modified files" +fi + +# Extract the start line and count from the changeset header. +# +# The format is: +# +# @@ [+-]FROM-START,FROM-COUNT [+-]TO-START,TO-COUNT @@ +# +# Note that if the changeset has only one line then the count is omitted. +# +function changeset_start () +{ + echo "$1" | sed -e 's/^@@ [^ ]* [+-]\([^, ]*\).*$/\1/' +} + +function changeset_count () +{ + local r + r="$(echo "$1" | sed -n -e 's/^@@ [^ ]* [+-][^,]*,\([^ ]*\) @@$/\1/p')" + if [ -z "$r" ]; then + r="1" + fi + echo "$r" +} + +#changeset_start "@@ -12,3 +13,11 @@" +#changeset_count "@@ -12,3 +13,11 @@" +#changeset_start "@@ -12 +13 @@" +#changeset_count "@@ -12 +13 @@" + +h= +if [ "$(basename "$modified")" = "list" ]; then + # + # This is a list of notes. The plan is to get the start line numbers for the + # first and last change set. We then scan the list line by line looking for + # headers until we hit the start of the first change set: the last header + # that we see should be our header. We also continue scanning until we hit + # the end of the last changeset: if we see any headers then we are updating + # multiple notes. + # + + # Get the diff output as a list of change set headers. + # + diff="$(git diff -U0 | sed -n -e '/^@@ /p')" + + fc="$(echo "$diff" | head -n 1)" + lc="$(echo "$diff" | tail -n 1)" + + sl="$(changeset_start "$fc")" + el="$(($(changeset_start "$lc") + $(changeset_count "$lc") - 1))" + + # Scan the list looking for headers. + # + l= + c="0" + while read l || [ -n "$l" ]; do + + # Stop if we are past the end line. + # + c="$(($c + 1))" + if [ "$c" -gt "$el" ]; then + break + fi + + # See if this is a header. + # + if echo "$l" | grep -q '^[-?!] '; then + + # If we are past the start line then we are modifying multiple notes. + # + if [ "$c" -gt "$sl" ]; then + error "error: multiple modified notes in $modified:${sl}-${el}" + fi + + # This is the last header. + # + h="$l" + fi + done < <(cat "$modified") + + if [ -z "$h" ]; then + error "error: unable to find note header for $modified:${sl}-${el}" + fi +else + # This is a file note. All we need to do is get its header (the first line). + # + h="$(head -n 1 "$modified")" +fi + +# Header should start with one of [-?!]. +# +sum="$(echo "$h" | sed -n -re 's/^[-?!] ([^[]*)( \[.*\])?$/\1/p')" + +if [ -z "$sum" ]; then + error "error: unable to parse note header '$h'" +fi + +# By convention the first label is a note type (bug, feature, etc). +# +type="$(echo "$h" | sed -n -re 's/^[^[]*\[([^ ]*).*\]$/\1/p')" + +if [ -z "$type" ]; then + error "error: note header does not include note type as first label" +fi + +# Ok, all looks good so add, commit and push the change. +# +git add "$modified" +git ci -m "Update $type: $sum" + +if [ "$push" = "y" ]; then + git push +fi |