diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-15 03:29:20 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2016-09-15 03:29:20 +0200 |
commit | a0ae430f01bb8ab0a98cce2203435a286dd89ff7 (patch) | |
tree | 664b1b0b326cdbd9719ba016f580c5cacb91c7b4 /add |
Initial spec version and add script
Diffstat (limited to 'add')
-rwxr-xr-x | add | 113 |
1 files changed, 113 insertions, 0 deletions
@@ -0,0 +1,113 @@ +#! /usr/bin/env bash + +# Commit and push a new 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 + +untracked="$(git status --porcelain | sed -n -e 's/^?? \(.*\)/\1/p')" +modified="$(git status --porcelain | sed -n -e 's/^ M \(.*\)/\1/p')" + +uc="$(echo "$untracked" | wc -w)" +mc="$(echo "$modified" | wc -w)" + +if [ "$uc" -gt 0 -a "$mc" -gt 0 ]; then + error "error: multiple untracked/modified files" +fi + +# Add the tracked file to index with --intent-to-add so that we can diff it +# the same way as modified. The not so nice thing about this approach is that +# we have to remember to reset it if things go badly. +# +if [ "$uc" -gt 0 ]; then + git add --intent-to-add "$untracked" + modified="$untracked" +fi + +# Get the diff output skipping the header (the first four lines until the +# first changeset). +# +diff="$(git diff -U0 | sed -n -e '/^@@/,$p')" +dc="$(echo "$diff" | wc -l)" + +# Get the changeset. While we don't care for leading or trailing empty lines +# down the line, we do want them in the count. And preserving them in program +# substitution is more difficult than one would think. +# +cset="$(echo "$diff" | sed -n -e 's/^+\(.*\)/\1/p')" +cc="$(echo "$diff" | sed -n -e 's/^+\(.*\)/\1/p' | wc -l)" + +# We should only have one changeset and it should only have added lines. Note +# that this is always the case for a new file. +# +if [ "$dc" -ne "$(($cc + 1))" ]; then + info "error: multiple changesets or non-add changes" + git diff -U0 + exit 1 +fi + +# Get the first non-empty line which should be the header. +# +l= +while read l || [ -n "$l" ]; do + if [ -n "$l" ]; then + break + fi +done < <(echo "$cset") + +# Should start with one of [-?!]. +# +sum="$(echo "$l" | sed -n -re 's/^[-?!] ([^[]*)( \[.*\])?$/\1/p')" + +if [ -z "$sum" ]; then + info "error: first line does not appear to be a note header" + info "info: first line is '$l'" + exit 1 +fi + +# By convention the first label is a note type (bug, feature, etc). +# +type="$(echo "$l" | sed -n -re 's/^[^[]*\[([^ ]*).*\]$/\1/p')" + +if [ -z "$type" ]; then + error "error: note header does not include note type as first label" +fi + +#@@ Maybe check known note types and warn if not one of them? +# + +# Ok, all looks good so add, commit and push the change. +# +git add "$modified" +git ci -m "Add $type: $sum" + +if [ "$push" = "y" ]; then + git push +fi |