diff --git a/developer/bin/develop_brew_cask b/developer/bin/develop_brew_cask index 5d82071eaa..d7123abd61 100755 --- a/developer/bin/develop_brew_cask +++ b/developer/bin/develop_brew_cask @@ -3,17 +3,43 @@ # develop_brew_cask # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### configurable global variables +### + +tap_subdir="Library/Taps/phinze-cask" + +### +### functions +### + +warn () { + local message="$@" + if ! [[ $message =~ "\n"$ ]]; then + message="${message}\n" + fi + printf "$message" 1>&2 +} + +die () { + warn "$@" + exit 1 +} cd_to_project_root () { local script_dir="$(/usr/bin/dirname $0)" cd "$script_dir" local git_root="$(git rev-parse --show-toplevel)" if [[ -z "$git_root" ]]; then - printf "Could not find git project root" - exit 1; + die "ERROR: Could not find git project root" fi cd "$git_root" } @@ -22,15 +48,22 @@ cd_to_version_dir () { local cellar_dir="$1" local version_dir="$2" if [[ -z "$version_dir" ]]; then - printf "Can't get version dir under $cellar_dir/\n"; - exit 1; + die "ERROR: Could not find version dir under $cellar_dir/" fi cd "$cellar_dir/$version_dir" } +not_inside_homebrew () { + local tap_dir="$1" + local git_root="$2" + if [[ "$(/usr/bin/stat -L -f '%i' "$tap_dir")" -eq "$(/usr/bin/stat -L -f '%i' "$git_root")" ]]; then + die "\nERROR: Run this script in your private repo, not inside Homebrew.\n" + fi +} + create_dev_links () { - local git_root="$1" - local tap_dir="$2" + local tap_dir="$1" + local git_root="$2" /bin/mv rubylib production_rubylib /bin/mv Casks production_Casks /bin/ln -s "$git_root/Casks" . @@ -40,46 +73,44 @@ create_dev_links () { /bin/mv Casks production_Casks /bin/ln -s "$git_root/Casks" . /bin/ln -s "$git_root/lib" . + printf "brew-cask is now in development mode\n" + printf "Note: it is not safe to run 'brew update' while in development mode\n" } +### +### main +### + _develop_brew_cask () { - # configurable - local tap_subdir="Library/Taps/phinze-cask" - # initialization - cd_to_project_root; - local git_root="$(pwd)" + cd_to_project_root + local git_root="$(/bin/pwd)" local brew_prefix="$(brew --prefix)" local cellar_dir="$brew_prefix/Cellar/brew-cask" local version_dir="$(/bin/ls "$cellar_dir/" | /usr/bin/sort | /usr/bin/tail -1)" local tap_dir="$brew_prefix/$tap_subdir" # sanity check - if [[ "$(/usr/bin/stat -L -f '%i' "$tap_dir")" -eq "$(/usr/bin/stat -L -f '%i' "$git_root")" ]]; then - printf "\nERROR: run this script in your private repo, not inside Homebrew.\n"; - exit 1; - fi + not_inside_homebrew "$tap_dir" "$git_root" # action - cd_to_version_dir "$cellar_dir" "$version_dir"; + cd_to_version_dir "$cellar_dir" "$version_dir" if [[ -e "production_rubylib" ]]; then - printf "brew-cask is already set up for development\n"; - exit 1 + die "brew-cask is already set up for development" else - create_dev_links "$git_root" "$tap_dir"; - printf "brew-cask is now in development mode\n" - printf "Note: it is not safe to run 'brew update' while in development mode\n" + create_dev_links "$tap_dir" "$git_root" fi } +# process args if [[ $1 =~ ^-+h(elp)?$ ]]; then printf "develop_brew_cask Symlink private repo directories into Homebrew's Cellar, so -that the 'brew cask' command will use the current development -branch in your private repo. +that the 'brew cask' command will use code and Casks from +the current development branch in your private repo. Saves the production Homebrew directories under new names. @@ -92,6 +123,7 @@ mode is in effect. exit fi -_develop_brew_cask "$@"; +# dispatch main +_develop_brew_cask "${@}" # diff --git a/developer/bin/get_release_tag b/developer/bin/get_release_tag index da7ecd8086..d7932f78cc 100755 --- a/developer/bin/get_release_tag +++ b/developer/bin/get_release_tag @@ -3,20 +3,36 @@ # get_release_tag # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### -opt_next=''; -opt_latest=''; -opt_verbose=''; +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions -die () { - local message="$@"; +### +### global variables +### + +opt_next='' +opt_latest='' +opt_verbose='' + +### +### functions +### + +warn () { + local message="$@" if ! [[ $message =~ "\n"$ ]]; then message="${message}\n" fi printf "$message" 1>&2 +} + +die () { + warn "$@" exit 1 } @@ -25,23 +41,23 @@ cd_to_project_root () { cd "$script_dir" local git_root="$(git rev-parse --show-toplevel)" if [[ -z "$git_root" ]]; then - die "Could not find git project root" + die "ERROR: Could not find git project root" fi cd "$git_root" } verify_git_object_is_new () { if git rev-parse --verify "$1" >/dev/null 2>&1; then - die "\nERROR: proposed new tag: '$1' already exists as a commit object\n\n" + die "\nERROR: Proposed new tag: '$1' already exists as a commit object\n\n" fi } sanity_check_parsed_version () { if [[ $# -ne 3 ]]; then - die "Error: can't parse version tag, wrong number of elements" + die "ERROR: Could not parse version tag: wrong number of elements" fi if ! [[ $1 =~ ^v[0-9]+$ ]]; then - die "Error: can't parse version tag, does not start with v[0-9]" + die "ERROR: Could not parse version tag: does not start with v[0-9]" fi } @@ -71,7 +87,7 @@ generate_next_major_tag () { generate_next_minor_tag () { local -a version_elts - IFS='.' read -a version_elts <<< "$1"; + IFS='.' read -a version_elts <<< "$1" sanity_check_parsed_version "${version_elts[@]}" (( version_elts[1] += 1 )) # increment minor field version_elts[2]='0' # reset patch field @@ -123,30 +139,34 @@ See RELEASING.md for more information. fi elif [[ $arg =~ ^-+patch$ ]]; then if [[ "$opt_next" == 'major' ]]; then - die "Error: -patch is incompatible with -major"; + die "ERROR: -patch is incompatible with -major" fi opt_next='patch' elif [[ $arg =~ ^-+major$ ]]; then if [[ "$opt_next" == 'patch' ]]; then - die "Error: -patch is incompatible with -major"; + die "ERROR: -patch is incompatible with -major" fi opt_next='major' elif [[ $arg =~ ^-+latest$ ]]; then opt_latest='true' else - die "Error: unknown argument '$arg'" + die "ERROR: Unknown argument '$arg'" fi if [[ -n "$opt_latest" && -n "$opt_next" ]]; then - die "Error: -latest is incompatible with -next/-patch/-major" + die "ERROR: -latest is incompatible with -next/-patch/-major" fi done } +### +### main +### + _get_release_tag () { - cd_to_project_root; + cd_to_project_root local latest_tag="$(git describe --tags --abbrev=0 2>/dev/null)" if [[ -z "$latest_tag" ]]; then - die "Error: no recent tag found" + die "ERROR: No recent tag found" elif [[ -z "$opt_next" ]]; then if [[ -n "$opt_verbose" ]]; then printf "Latest tag\t" @@ -159,12 +179,13 @@ _get_release_tag () { elif [[ "$opt_next" == 'patch' ]]; then generate_next_patch_tag "$latest_tag" else - die "Error: should not happen. Unknown argument?" + die "ERROR: Should not happen. Unknown argument?" fi } -process_args "$@"; +process_args "${@}" -_get_release_tag; +# dispatch main +_get_release_tag # diff --git a/developer/bin/list_apps_in_pkg b/developer/bin/list_apps_in_pkg index 2a1b863945..4d5ece1f73 100755 --- a/developer/bin/list_apps_in_pkg +++ b/developer/bin/list_apps_in_pkg @@ -3,41 +3,82 @@ # list_apps_in_pkg # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### -_list_apps_in_pkg () { +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions - local tmpdir=`/usr/bin/mktemp -d -t list_apps_in_pkg` - trap "/bin/rm -rf '$tmpdir'" EXIT +### +### global variables +### - /usr/sbin/pkgutil --expand "$1" "$tmpdir/unpack" +opt_lax='' +opt_pkg='' +tmpdir='' - { - # source 1 - /usr/bin/find "$tmpdir" -name PackageInfo -print0 | \ - /usr/bin/xargs -0 /usr/bin/perl -0777 -ne \ - 'while (m{&2 +} + +die () { + warn "$@" + exit 1 +} + +app_source_1 () { + /usr/bin/find "$tmpdir" -name PackageInfo -print0 | \ + /usr/bin/xargs -0 /usr/bin/perl -0777 -ne \ + 'while (m{ +process_args () { + local arg + if [[ "$#" -eq 0 ]]; then + die "ERROR: A file argument is required" + else + opt_pkg="${!#}" # last arg + fi + for arg in "$@"; do + if [[ $arg =~ ^-+h(elp)?$ ]]; then + printf "list_apps_in_pkg [ -lax ] Given a package file, extract a list of candidate App names from inside the pkg, which may be useful for naming a Cask. @@ -48,7 +89,12 @@ If an App of the listed name is already installed in /Applications or ~/Applications, it will be followed by a plus symbol '(+)' in the output. This can be verified via 'ls' or the Finder. -This script is imperfect. +Arguments + + -lax Be less selective in looking for App names. Generate + more, but less accurate, guesses. + +Bugs: This script is imperfect. - It does not fully parse PackageInfo files - An App can be hidden within a nested archive and not found - Some pkg files simply don't contain any Apps @@ -56,9 +102,47 @@ This script is imperfect. See CONTRIBUTING.md and 'man pkgutil' for more information. " - exit -fi + exit + elif [[ $arg =~ ^-+lax$ ]]; then + opt_lax='true' + elif [[ "$arg" = "$opt_pkg" ]]; then + opt_latest='true' + else + die "ERROR: Unknown argument '$arg'" + fi + done + if ! [[ -e "$opt_pkg" ]]; then + die "ERROR: No such pkg file: '$opt_pkg'" + fi +} -_list_apps_in_pkg "$@"; +### +### main +### + +_list_apps_in_pkg () { + + tmpdir=`/usr/bin/mktemp -d -t list_apps_in_pkg` + trap "/bin/rm -rf '$tmpdir'" EXIT + + /usr/sbin/pkgutil --expand "$opt_pkg" "$tmpdir/unpack" + + { + # strings that look like App names (Something.app) + app_source_1; + app_source_2; + app_source_3; + if [[ -n "$opt_lax" ]]; then + app_source_4; + fi + } | \ + merge_sources | \ + mark_up_sources +} + +process_args "${@}" + +# dispatch main +_list_apps_in_pkg # diff --git a/developer/bin/list_ids_in_pkg b/developer/bin/list_ids_in_pkg index ea38ec78c5..a7a2fff687 100755 --- a/developer/bin/list_ids_in_pkg +++ b/developer/bin/list_ids_in_pkg @@ -3,29 +3,67 @@ # list_ids_in_pkg # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### global variables +### + +tmpdir='' + +### +### functions +### + +bundle_id_source_1 () { + /usr/bin/find "$tmpdir" -name PackageInfo -print0 | \ + /usr/bin/xargs -0 /usr/bin/perl -0777 -ne \ + 'while (m{/dev/null 2>&1 && printf " (+)"; printf "\n"' +} + +### +### main +### _list_ids_in_pkg () { - local tmpdir=`/usr/bin/mktemp -d -t list_ids_in_pkg` + tmpdir=`/usr/bin/mktemp -d -t list_ids_in_pkg` trap "/bin/rm -rf '$tmpdir'" EXIT /usr/sbin/pkgutil --expand "$1" "$tmpdir/unpack" - /usr/bin/find "$tmpdir" -name PackageInfo -print0 | \ - /usr/bin/xargs -0 /usr/bin/perl -0777 -ne \ - 'while (m{/dev/null 2>&1 && printf " (+)"; printf "\n"' + { + # emit strings that look like bundle ids + bundle_id_source_1; + } | \ + merge_sources | \ + clean_sources | \ + mark_up_sources } +# process args if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then printf "list_ids_in_pkg @@ -55,6 +93,7 @@ See CONTRIBUTING.md and 'man pkgutil' for more information. exit fi -_list_ids_in_pkg "$@"; +# dispatch main +_list_ids_in_pkg "${@}" # diff --git a/developer/bin/list_loaded_kext_ids b/developer/bin/list_loaded_kext_ids index 03a0041509..caca550368 100755 --- a/developer/bin/list_loaded_kext_ids +++ b/developer/bin/list_loaded_kext_ids @@ -3,14 +3,26 @@ # list_loaded_kext_ids # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### main +### _list_loaded_kext_ids () { - /usr/sbin/kextstat -kl | /usr/bin/cut -c53- | /usr/bin/cut -f1 -d' ' | /usr/bin/egrep -v '^com\.apple\.' + /usr/sbin/kextstat -kl | \ + /usr/bin/cut -c53- | \ + /usr/bin/cut -f1 -d' ' | \ + /usr/bin/egrep -v '^com\.apple\.' } +# process args if [[ $1 =~ ^-+h(elp)?$ ]]; then printf "list_loaded_kext_ids @@ -27,6 +39,7 @@ See CONTRIBUTING.md for more information. exit fi -_list_loaded_kext_ids "$@"; +# dispatch main +_list_loaded_kext_ids "${@}" # diff --git a/developer/bin/list_recent_pkg_ids b/developer/bin/list_recent_pkg_ids index 3bf92ed376..e2c16af3a3 100755 --- a/developer/bin/list_recent_pkg_ids +++ b/developer/bin/list_recent_pkg_ids @@ -3,9 +3,17 @@ # list_recent_pkg_ids # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### main +### _list_recent_pkg_ids () { /bin/ls -t /var/db/receipts | \ @@ -15,6 +23,7 @@ _list_recent_pkg_ids () { /usr/bin/head -10 } +# process args if [[ $1 =~ ^-+h(elp)?$ ]]; then printf "list_recent_pkg_ids @@ -31,6 +40,7 @@ See CONTRIBUTING.md for more information. exit fi -_list_recent_pkg_ids "$@"; +# dispatch main +_list_recent_pkg_ids "${@}" # diff --git a/developer/bin/production_brew_cask b/developer/bin/production_brew_cask index 416de5be16..e0c3fbebdd 100755 --- a/developer/bin/production_brew_cask +++ b/developer/bin/production_brew_cask @@ -3,17 +3,43 @@ # production_brew_cask # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### configurable global variables +### + +tap_subdir="Library/Taps/phinze-cask" + +### +### functions +### + +warn () { + local message="$@" + if ! [[ $message =~ "\n"$ ]]; then + message="${message}\n" + fi + printf "$message" 1>&2 +} + +die () { + warn "$@" + exit 1 +} cd_to_project_root () { local script_dir="$(/usr/bin/dirname $0)" cd "$script_dir" local git_root="$(git rev-parse --show-toplevel)" if [[ -z "$git_root" ]]; then - printf "Could not find git project root" - exit 1; + die "ERROR: Could not find git project root" fi cd "$git_root" } @@ -22,12 +48,19 @@ cd_to_version_dir () { local cellar_dir="$1" local version_dir="$2" if [[ -z "$version_dir" ]]; then - printf "Can't get version dir under $cellar_dir/\n"; - exit 1; + die "ERROR: Could not find version dir under $cellar_dir/" fi cd "$cellar_dir/$version_dir" } +not_inside_homebrew () { + local tap_dir="$1" + local git_root="$2" + if [[ "$(/usr/bin/stat -L -f '%i' "$tap_dir")" -eq "$(/usr/bin/stat -L -f '%i' "$git_root")" ]]; then + die "\nERROR: Run this script in your private repo, not inside Homebrew.\n" + fi +} + remove_dev_links () { local tap_dir="$1" /bin/rm rubylib Casks @@ -37,53 +70,54 @@ remove_dev_links () { /bin/rm lib Casks /bin/mv production_lib lib /bin/mv production_Casks Casks + printf "brew-cask is now in production mode\n" + printf "It is safe to run 'brew update' if you are in production mode for all Caskroom repos.\n" } +### +### main +### + _production_brew_cask () { - # configurable - local tap_subdir="Library/Taps/phinze-cask" - # initialization - cd_to_project_root; - local git_root="$(pwd)" + cd_to_project_root + local git_root="$(/bin/pwd)" local brew_prefix="$(brew --prefix)" local cellar_dir="$brew_prefix/Cellar/brew-cask" local version_dir="$(/bin/ls "$cellar_dir/" | /usr/bin/sort | /usr/bin/tail -1)" local tap_dir="$brew_prefix/$tap_subdir" # sanity check - if [[ "$(/usr/bin/stat -L -f '%i' "$tap_dir")" -eq "$(/usr/bin/stat -L -f '%i' "$git_root")" ]]; then - printf "\nERROR: run this script in your private repo, not inside Homebrew.\n" - exit 1; - fi + not_inside_homebrew "$tap_dir" "$git_root" # action - cd_to_version_dir "$cellar_dir" "$version_dir"; + cd_to_version_dir "$cellar_dir" "$version_dir" if [[ -e "production_rubylib" ]]; then - remove_dev_links "$tap_dir"; - printf "brew-cask is now in production mode\n" - printf "It is safe to run 'brew update'\n" + remove_dev_links "$tap_dir" else - printf "brew-cask is already set up for production\n" - exit 1 + die "brew-cask is already set up for production" fi } +# process args if [[ $1 =~ ^-+h(elp)?$ ]]; then printf "production_brew_cask -Undo all symlinks created by 'develop_brew_cask' so that -the 'brew cask' command will use only released code within -Homebrew. +Undo all symlinks created by 'develop_brew_cask' so that the +'brew cask' command will use only released code and Casks +within Homebrew. -After running this command it is safe to run 'brew update'. +After running this command it is safe to run 'brew update', +unless you are using similar scripts to create symlinks into +other Caskroom development repos. " exit fi -_production_brew_cask "$@"; +# dispatch main +_production_brew_cask "${@}" # diff --git a/developer/bin/project_stats b/developer/bin/project_stats index 25dfe64c13..1c50c39d71 100755 --- a/developer/bin/project_stats +++ b/developer/bin/project_stats @@ -5,77 +5,96 @@ # stats on project/release from git database # -set -e; # exit on any uncaught error -set +o histexpand; # don't expand history expressions -shopt -s nocasematch; # case-insensitive regular expressions +### +### settings +### + +set -e # exit on any uncaught error +set +o histexpand # don't expand history expressions +shopt -s nocasematch # case-insensitive regular expressions + +### +### configurable global variables +### + +# these paths relative to project root +declare -a cask_paths=(Casks) +declare -a code_paths=(bin developer lib test brew-cask.rb Rakefile Gemfile Gemfile.lock .travis.yml .gitignore) +declare -a doc_paths=(doc LICENSE "*.md") +end_object="HEAD" + +### +### global variables +### + +cask_authors='' + +### +### functions +### + +warn () { + local message="$@" + if ! [[ $message =~ "\n"$ ]]; then + message="${message}\n" + fi + printf "$message" 1>&2 +} + +die () { + warn "$@" + exit 1 +} cd_to_project_root () { local script_dir="$(/usr/bin/dirname $0)" cd "$script_dir" local git_root="$(git rev-parse --show-toplevel)" if [[ -z "$git_root" ]]; then - printf "Could not find git project root" - exit 1; + die "ERROR: Could not find git project root" fi cd "$git_root" } warn_if_off_branch () { - local branch="$(git rev-parse --abbrev-ref HEAD)" local wanted_branch='master' if [[ -n "$1" ]]; then wanted_branch="$1" fi - if [[ "$branch" != "$wanted_branch" ]]; then - printf "\nWARNING: you are running from branch '$branch', not '$wanted_branch'\n\n" + + local current_branch="$(git rev-parse --abbrev-ref HEAD)" + if ! [[ "$current_branch" = "$wanted_branch" ]]; then + warn "\nWARNING: you are running from branch '$current_branch', not '$wanted_branch'\n\n" fi } verify_git_object () { - if ! git rev-parse --verify "$1" > /dev/null 2>/dev/null; then - printf "\nERROR: No such commit object: $1\n\n" - exit 1 + local object="$1" + + if ! git rev-parse --verify "$object" -- >/dev/null 2>&1; then + die "\nERROR: No such commit object: '$object'\n\n" fi } -_homebrew_cask_project_stats () { - - local initial_commit="5a0d1d5556e3f963a0d34da46e16ecffa59ea2fc" - local start_object="$initial_commit" - local end_object="HEAD" - - # these paths relative to project root - local cask_paths="Casks" - local code_paths="bin developer lib test brew-cask.rb Rakefile Gemfile Gemfile.lock" - local doc_paths="LICENSE *.md" - - cd_to_project_root; - warn_if_off_branch 'master'; - - if [[ "$1" = 'release' ]]; then - start_object="$(git describe --tags --abbrev=0)" - elif [[ -n "$1" ]]; then - start_object="$1" - fi - verify_git_object "$start_object"; +print_contributor_stats () { + local start_object="$1" + local initial_commit="$2" + local git_log_cmd="git log --no-merges --format='%ae' ${start_object}..${end_object}" printf "Unique contributors" - if [[ "$start_object" != "$initial_commit" ]]; then + if ! [[ "$start_object" = "$initial_commit" ]]; then printf " since $start_object" fi printf "\n" - - local git_log_cmd="git log --no-merges --format='%ae' ${start_object}..${end_object}" - - local cask_authors="$($git_log_cmd -- $cask_paths | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" + cask_authors="$($git_log_cmd -- "${cask_paths[@]}" | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" printf " Casks\t$cask_authors\n" printf " code\t" - $git_log_cmd -- $code_paths | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l + $git_log_cmd -- "${code_paths[@]}" | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l printf " docs\t" - $git_log_cmd -- $doc_paths | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l + $git_log_cmd -- "${doc_paths[@]}" | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l printf " any\t" - $git_log_cmd -- . | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l - if [[ "$start_object" != "$initial_commit" ]]; then + $git_log_cmd -- . | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l + if ! [[ "$start_object" = "$initial_commit" ]]; then local alltime_contribs="$(git log --no-merges --format='%ae' ${initial_commit}..${end_object} -- . | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" local prior_contribs="$(git log --no-merges --format='%ae' ${initial_commit}..${start_object} -- . | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" # arithmetic removes whitespace @@ -84,13 +103,42 @@ _homebrew_cask_project_stats () { printf "\nAll-time contributors\t$alltime_contribs\n" printf "New contributors since $start_object\t$new_contribs\n" fi - printf "\n" +} - if [[ "$start_object" != "$initial_commit" ]]; then - local new_casks="$(git diff --name-status "$start_object" "$end_object" -- $cask_paths | /usr/bin/grep '^A.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" - local deleted_casks="$(git diff --name-status "$start_object" "$end_object" -- $cask_paths | /usr/bin/grep '^D.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" - local updated_casks="$(git diff --name-status "$start_object" "$end_object" -- $cask_paths | /usr/bin/grep '^M.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" +print_commit_stats () { + local start_object="$1" + local initial_commit="$2" + + local git_log_cmd="git log --no-merges --format='%ae' ${start_object}..${end_object}" + printf "Commit count" + if ! [[ "$start_object" = "$initial_commit" ]]; then + printf " since $start_object" + fi + printf "\n" + printf " Casks\t" + $git_log_cmd -- "${cask_paths[@]}" | /usr/bin/wc -l + printf " code\t" + $git_log_cmd -- "${code_paths[@]}" | /usr/bin/wc -l + printf " docs\t" + $git_log_cmd -- "${doc_paths[@]}" | /usr/bin/wc -l + printf " any\t" + $git_log_cmd -- . | /usr/bin/wc -l + if ! [[ "$start_object" = "$initial_commit" ]]; then + printf "\nAll-time commits\t" + git log --no-merges --format='%ae' "${initial_commit}".."${end_object}" -- . | /usr/bin/wc -l + fi + printf "\n" +} + +print_cask_stats () { + local start_object="$1" + local initial_commit="$2" + + if ! [[ "$start_object" = "$initial_commit" ]]; then + local new_casks="$(git diff --name-status "$start_object" "$end_object" -- "${cask_paths[@]}" | /usr/bin/grep '^A.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" + local deleted_casks="$(git diff --name-status "$start_object" "$end_object" -- "${cask_paths[@]}" | /usr/bin/grep '^D.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" + local updated_casks="$(git diff --name-status "$start_object" "$end_object" -- "${cask_paths[@]}" | /usr/bin/grep '^M.*\.rb' | cut -f2 | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" # arithmetic removes whitespace ((cask_authors += 0)) ((deleted_casks += 0)) @@ -100,10 +148,36 @@ _homebrew_cask_project_stats () { fi printf "Total current Casks in HEAD\t" - /usr/bin/find $cask_paths -name '*.rb' | /usr/bin/wc -l - + /usr/bin/find "${cask_paths[@]}" -name '*.rb' | /usr/bin/wc -l } +### +### main +### + +_project_stats () { + local arg_object="$1" + + cd_to_project_root + warn_if_off_branch 'master' + + local initial_commit="$(git log --pretty=format:%H -- | /usr/bin/tail -1)" + verify_git_object "$initial_commit" + local start_object="$initial_commit" + + if [[ "$arg_object" = 'release' ]]; then + start_object="$(./developer/bin/get_release_tag)" + elif [[ -n "$arg_object" ]]; then + start_object="$arg_object" + fi + verify_git_object "$start_object" + + print_contributor_stats "$start_object" "$initial_commit" + print_commit_stats "$start_object" "$initial_commit" + print_cask_stats "$start_object" "$initial_commit" +} + +# process args if [[ $1 =~ ^-+h(elp)?$ ]]; then printf "project_stats [ ] @@ -119,6 +193,7 @@ Without argument, show statistics since first commit. exit fi -_homebrew_cask_project_stats "$@"; +# dispatch main +_project_stats "${@}" #