precursor 0.2.3

Pre-protocol payload tagging, similarity clustering, and packet/firmware triage CLI.
#!/bin/bash

set -e

function update_version {
  manifest="$1"
  semver="$2"

  sed -i 's/^version = ".*"\s\+#:version$/version = "'$semver'"  #:version/g' "$manifest"
}

function current_version {
  manifest="$1"
  grep '^version' "$manifest" | sed 's/.*"\([0-9]\+\.[0-9]\+\.[0-9]\+\)"/\1/g'
}

function next_version {
  cur="$1"
  nopatch=${cur%.*}
  patch=${cur##*.}
  patchplus=$((patch + 1))
  printf "%s.%s\n" $nopatch $patchplus
}

function pkg_name {
  manifest="$1"
  grep -E '^name = "[^"]+"$' "$manifest" \
    | head -n1 \
    | grep -Po '(?<=name = ")[^"]+'
}

function tag_name {
  manifest="$1"
  version="$2"

  root="$(git rev-parse --show-toplevel)"
  if [ "$root/Cargo.toml" = "$(realpath "$manifest")" ]; then
    echo "$version"
  else
    pkg="$(pkg_name "$manifest")"
    echo "$pkg-$version"
  fi
}

release=yes
push=yes
while true; do
  case "$1" in
    --no-release) release= && shift ;;
    --no-push) push= && shift ;;
    -*)
      echo "Usage: $(basename $0) [ --no-release --no-push ] [ path/to/Cargo.toml [ semver ] ]" >&2
      exit 1
      ;;
    *) break ;;
  esac
done

case $# in
  0)
    manifest=Cargo.toml
    semver=$(next_version $(current_version "$manifest"))
    ;;
  1)
    manifest="$1"
    semver=$(next_version $(current_version "$manifest"))
    ;;
  2)
    manifest="$1"
    semver="$2"
    ;;
  *)
    echo "Usage: $(basename $0) [ --no-release ] [ path/to/Cargo.toml [ semver ] ]" >&2
    exit 1
    ;;
esac

if [ -n "$(git status --untracked-files=no --porcelain)" ]; then
  echo "Git working directory is not clean." >&2
  exit 1
fi
if ! grep -q '#:version' "$manifest"; then
  echo "Could not find '#:version' tag in $manifest" >&2
  exit 1
fi

update_version "$manifest" "$semver"
tag="$(tag_name "$manifest" "$semver")"
pkg="$(pkg_name "$manifest")"
if [ -f Cargo.toml ] && grep -E -q '\[\[bin\]\]' Cargo.toml; then
  cargo update -p "$pkg"
fi
git commit -a -m "$tag"
git tag -s -a "$tag" -m "$tag"

if [ -n "$release" ]; then
  (
    cd "$(dirname "$manifest")"
    cargo publish
  )
  if [ -n "$push" ]; then
    for remote in origin github home; do
      if git remote | grep -q "$remote"; then
        git push "$remote" master
        git push "$remote" "$tag"
      fi
    done
  fi
fi