From 8d5a06ed146f6f4a8fd77c922dfc268bf377420e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Galv=C3=A3o?= Date: Fri, 29 Sep 2017 22:49:57 +0100 Subject: [PATCH] Remove some dev scripts (#39115) * Removed irregular_cask_whitespace * Removed project_stats * Remove the_long_tail --- developer/bin/irregular_cask_whitespace | 133 ------------- developer/bin/project_stats | 234 ---------------------- developer/bin/the_long_tail | 252 ------------------------ 3 files changed, 619 deletions(-) delete mode 100755 developer/bin/irregular_cask_whitespace delete mode 100755 developer/bin/project_stats delete mode 100755 developer/bin/the_long_tail diff --git a/developer/bin/irregular_cask_whitespace b/developer/bin/irregular_cask_whitespace deleted file mode 100755 index 62a60ae737..0000000000 --- a/developer/bin/irregular_cask_whitespace +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash -# -# irregular_cask_whitespace -# -# find irregular whitespace in Cask files -# -# notes -# -# requires a recent-ish Perl with Unicode support, probably 5.14 -# or better. -# -# bugs -# -# todo -# - -### -### settings -### - -set -e -set -o pipefail -set +o histexpand -set -o nounset -shopt -s nocasematch -shopt -s nullglob - -### -### functions -### - -warn () { - local message="$@" - message="${message//\\t/$'\011'}" - message="${message//\\n/$'\012'}" - message="${message%"${message##*[![:space:]]}"}" - printf "%s\n" "$message" 1>&2 -} - -die () { - warn "$@" - exit 1 -} - -### -### main -### - -_irregular_cask_whitespace () { - local directory="$1" - cd "$directory" || die "Could not cd to '$directory'" - - printf "# No trailing newline at EOF\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{[^\n]\z}s' -- ./*.rb - - printf "\n# Extra trailing newline at EOF\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n{2}\z}s' -- ./*.rb - - printf "\n# Final 'end' indented\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{ end\s+\z}s' -- ./*.rb - - printf "\n# Extra newline before final end\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n\nend\s+\z}s' -- ./*.rb - - printf "\n# Extra newline before header\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n\ncask\s+:v\d\S*\s+=>}s' -- ./*.rb - - printf "\n# Extra newline after header\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{(?:\A|\n)cask\s+:v\d\S*\s+=>[^\n]+\n\n\s*(\S+)}s and $1 ne "if"' -- ./*.rb - - printf "\n# No empty line before uninstall\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n[^\n]+\n +uninstall }s' -- ./*.rb - - # todo? - # printf "\n# No empty line before caveats\n" - # perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n[^\n]+\n +caveats }s' -- ./*.rb - - printf "\n# Extra interior newlines\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n{3,}}s' -- ./*.rb - - printf "\n# Leading whitespace at BOF\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\A\s}s' -- ./*.rb - - printf "\n# Trailing whitespace at EOL (includes Tab/CR)\n" - perl -C32 -ne 'print " $ARGV\n" if m{\s\n}s' -- ./*.rb | sort | uniq - - printf "\n# Tabs\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\t}s' -- ./*.rb - - printf "\n# Carriage Returns\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\r}s' -- ./*.rb - - printf "\n# Misc Control Characters\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{[\x00-\x08\x0B-\x0C\x0E\x1F]}s' -- ./*.rb - - printf "\n# First indent not 2\n" - perl -C32 -0777 -ne 's{\A(.*?\n)?cask\s+[^\n]+\n+}{}s; print " $ARGV\n" unless m{\A \S}s' -- ./*.rb - - printf "\n# Indents not multiple of 2\n" - perl -C32 -0777 -ne 'print " $ARGV\n" if m{\n(?: ){0,} [a-z]}s' -- ./*.rb - - printf "\n# Unicode Space Characters\n" - # \x{0085}\x{0088}\x{0089} - perl -C32 -0777 -ne 'print " $ARGV\n" if m{[\x{008a}\x{00a0}\x{1680}\x{180e}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005}\x{2006}\x{2007}\x{2008}\x{2009}\x{200a}\x{200b}\x{2028}\x{2029}\x{202f}\x{205f}\x{2060}\x{3000}\x{feff}\x{e0020}]}s' -- ./*.rb - -} - -### -### argument processing -### - -if [[ "${1:-}" =~ ^-+h(elp)?$ ]]; then - printf "irregular_cask_whitespace - - Find irregular whitespace in Cask files within - -" - exit -fi - -if [ "$#" -ne 1 ]; then - die "Single directory argument required" -elif ! [ -d "$1" ]; then - die "No directory found at '$1'" -fi - -### -### dispatch -### - -_irregular_cask_whitespace "${@:-}" - -# diff --git a/developer/bin/project_stats b/developer/bin/project_stats deleted file mode 100755 index 652b6d7b33..0000000000 --- a/developer/bin/project_stats +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/bash -# -# project_stats -# -# stats on project/release from git database -# - -### -### 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 spec 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='' - -# prefer GNU xargs -xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')" - -### -### functions -### - -warn () { - local message="$@" - message="${message//\\t/$'\011'}" - message="${message//\\n/$'\012'}" - message="${message%"${message##*[![:space:]]}"}" - printf "%s\n" "$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 - die "ERROR: Could not find git project root" - fi - cd "$git_root" -} - -warn_if_off_branch () { - local wanted_branch='master' - if [[ -n "$1" ]]; then - wanted_branch="$1" - fi - - 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 () { - local object="$1" - - if ! git rev-parse --verify "$object" -- >/dev/null 2>&1; then - die "\nERROR: No such commit object: '$object'\n\n" - fi -} - -print_contributor_stats () { - local start_object="$1" - local initial_commit="$2" - - printf "====================\n" - printf "Contributors\n" - printf "====================\n" - - local -a git_log_cmd=("git" "log" "--no-merges" "--format='%ae'" "${start_object}..${end_object}") - printf "Unique contributors" - if ! [[ "$start_object" = "$initial_commit" ]]; then - printf " since %s" "${start_object#v}" - fi - printf "\n" - cask_authors="$("${git_log_cmd[@]}" -- "${cask_paths[@]}" | /usr/bin/sort | /usr/bin/uniq | /usr/bin/wc -l)" - printf " Casks\t%s\n" "$cask_authors" - printf " code\t" - "${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 - printf " any\t" - "${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 - ((alltime_contribs += 0)) - ((new_contribs = alltime_contribs - prior_contribs)) - printf "\nAll-time contributors\t%s\n" "$alltime_contribs" - printf "New contributors since %s\t%s\n" "${start_object#v}" "$new_contribs" - fi - printf "\n" -} - -print_commit_stats () { - local start_object="$1" - local initial_commit="$2" - - printf "====================\n" - printf "Commits\n" - printf "====================\n" - - local -a git_log_cmd=("git" "log" "--no-merges" "--format='%ae'" "${start_object}..${end_object}") - printf "Commit count" - if ! [[ "$start_object" = "$initial_commit" ]]; then - printf " since %s" "${start_object#v}" - 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_doc_stats () { - local start_object="$1" - local initial_commit="$2" - - printf "====================\n" - printf "Docs\n" - printf "====================\n" - - local -a git_log_cmd=("git" "log" "--no-merges" "--format='%ae'" "${start_object}..${end_object}") - printf "Doc contributors" - if ! [[ "$start_object" = "$initial_commit" ]]; then - printf " since %s" "${start_object#v}" - fi - printf "\n " - "${git_log_cmd[@]}" -- "${doc_paths[@]}" | /usr/bin/sort | /usr/bin/uniq | \ - /usr/bin/egrep -v $'^\'(paul\\.t\\.hinze@gmail\\.com|fanquake@users\\.noreply\\.github\\.com|fanquake@gmail\\.com|info@vitorgalvao\\.com|calebcenter@live\\.com|hagins\\.josh@gmail\\.com|dragon\\.vctr@gmail\\.com|github@adityadalal\\.com|adityadalal924@users\\.noreply\\.github\\.com)\'$' | \ - "$xargs" | /usr/bin/perl -pe 's{ }{, }g' # ' - printf "\n" -} - -print_cask_stats () { - local start_object="$1" - local initial_commit="$2" - - printf "====================\n" - printf "Casks\n" - 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)" - # arithmetic removes whitespace - ((cask_authors += 0)) - ((deleted_casks += 0)) - ((new_casks -= deleted_casks)) - ((updated_casks += 0)) - printf "%s Casks added (%s updated) by %s contributors since %s\n" "$new_casks" "$updated_casks" "$cask_authors" "${start_object#v}" - fi - - printf "Total current Casks in HEAD\t" - /usr/bin/find "${cask_paths[@]}" -name '*.rb' | /usr/bin/wc -l - printf "\n" -} - -### -### 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_doc_stats "$start_object" "$initial_commit" - print_cask_stats "$start_object" "$initial_commit" -} - -# process args -if [[ $1 =~ ^-+h(elp)?$ ]]; then - printf "project_stats [ ] - -With optional single argument, (eg a tag or commit-hash) -show statistics since that commit object. - -Use the special argument 'release' to calculate since the -most recent tag (usually the same as the last release). - -Without argument, show statistics since first commit. - -" - exit -fi - -# dispatch main -_project_stats "${@}" diff --git a/developer/bin/the_long_tail b/developer/bin/the_long_tail deleted file mode 100755 index 2a4cb8e7c3..0000000000 --- a/developer/bin/the_long_tail +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/env ruby -# -# the_long_tail -# -# A histogram view on contributor stats -# -# notes -# -# Since this script does not track file-renames in the git history, the -# dependence of Casks upon occasional contributors/non-maintainers can -# only be expressed as a range or lower bound. -# - -### -### dependencies -### - -require "open3" -require "set" - -### -### configurable constants -### - -BINS = [ - (1..10).to_a, - 100, - 1000, - ].flatten - -OCCASIONAL_CUTOFF = 5 - -CASK_PATH = "Casks".freeze - -# all maintainers, past and present -MAINTAINERS = %w[ - paul.t.hinze@gmail.com - fanquake@users.noreply.github.com - fanquake@gmail.com - kevin@suttle.io - leoj3n@gmail.com - nano@fdp.io - nanoid.xd@gmail.com - me@passcod.name - walker@pobox.com - info@vitorgalvao.com - calebcenter@live.com - ndr@qef.io - josh@joshbutts.com - goxberry@gmail.com - radek.simko@gmail.com - federicobond@gmail.com - claui@users.noreply.github.com - amorymeltzer@gmail.com - hagins.josh@gmail.com - dragon.vctr@gmail.com - mail@sebastianroeder.de - github@adityadalal.com - adityadalal924@users.noreply.github.com - ].freeze - -### -### git methods -### - -def cd_to_project_root - Dir.chdir File.dirname(File.expand_path(__FILE__)) - @git_root ||= Open3.popen3(*%w[ - git rev-parse --show-toplevel - ]) do |_stdin, stdout, _stderr| - begin - stdout.gets.chomp - rescue - end - end - Dir.chdir @git_root - @git_root -end - -def authors - @authors ||= Open3.popen3(*%w[ - git log --no-merges --format=%ae -- - ]) do |_stdin, stdout, _stderr| - h = {} - stdout.each_line do |line| - line.chomp! - h[line] ||= 0 - h[line] += 1 - end - h - end -end - -def casks_by_author - @casks_by_author ||= Open3.popen3(*%w[ - git log --no-merges --name-only --format=%ae -- - ], - CASK_PATH) do |_stdin, stdout, _stderr| - email = nil - h = {} - stdout.each_line.to_a.join("").split("\n\n").each do |paragraph| - if paragraph.include?("Casks/") - lines = paragraph.split("\n") - email = lines.pop - h[email] ||= Set.new - h[email].merge(lines.compact) - else - email = paragraph.chomp - end - end - h - end -end - -### -### filesystem methods -### - -def all_casks - @all_casks ||= Open3.popen2("/usr/bin/find", - CASK_PATH, - *%w[-type f -name *.rb]) do |_stdin, stdout| - stdout.each_line.map(&:chomp) - end -end - -### -### analysis and report methods -### - -def histogram - if @histogram.nil? - @histogram = Hash[*BINS.map { |elt| [elt, 0] }.flatten] - authors.each do |_name, num_commits| - bottom = 0 - BINS.each do |top| - @histogram[bottom] += 1 if num_commits >= bottom && num_commits < top - bottom = top - end - end - end - @histogram -end - -def historic_occasional_cask_set - @historic_occasional_cask_set = authors.each.collect do |name, num_commits| - if num_commits > OCCASIONAL_CUTOFF - nil - elsif !casks_by_author.key?(name) - nil - else - casks_by_author[name].to_a - end - end.flatten.compact.to_set -end - -def extant_occasional_cask_count - # avoid double-counting renames by intersecting with extant Casks - historic_occasional_cask_set.intersection(all_casks).count -end - -def historic_nonmaintainer_cask_set - @historic_nonmaintainer_cask_set = authors.each.collect do |name, _num_commits| - if MAINTAINERS.include?(name) - nil - else - casks_by_author[name].to_a - end - end.flatten.compact.to_set -end - -def extant_nonmaintainer_cask_count - # avoid double-counting renames by intersecting with extant Casks - historic_nonmaintainer_cask_set.intersection(all_casks).count -end - -def extant_occasional_cask_percentage - @extant_occasional_cask_percentage ||= (100 * extant_occasional_cask_count / all_casks.count).to_i -end - -def historic_occasional_cask_percentage - @historic_occasional_cask_percentage ||= (100 * historic_occasional_cask_set.count / all_casks.count).to_i -end - -def extant_nonmaintainer_cask_percentage - @extant_nonmaintainer_cask_percentage ||= (100 * extant_nonmaintainer_cask_count / all_casks.count).to_i -end - -def historic_nonmaintainer_cask_percentage - # this is so large, it might cross 100% - @historic_nonmaintainer_cask_percentage ||= [100, (100 * historic_nonmaintainer_cask_set.count / all_casks.count).to_i].min -end - -def onetime_author_percentage - @onetime_author_percentage ||= (100 * - histogram[1] / - authors.length).to_i -end - -def occasional_author_percentage - # why is it so hard to slice a hash? - @occasional_author_percentage ||= (100 * - (1..OCCASIONAL_CUTOFF).to_a.collect { |bin| histogram[bin] }.reduce(:+) / - authors.length).to_i -end - -def graph_width - if @graph_width.nil? - @graph_width = `/bin/stty size 2>/dev/null`.chomp.split(" ").last.to_i - @graph_width = 80 if @graph_width <= 0 - @graph_width -= 20 if @graph_width > 20 - end - @graph_width -end - -def graph_normalization - @graph_normalization ||= histogram.values.max.to_f -end - -def print_header - puts "Commits\tContributors" - puts "---------------------" -end - -def print_table - BINS.each do |bin| - plural = (bin % 10) == 0 ? "'s" : "" - graph = "." * ((histogram[bin] / graph_normalization) * graph_width) - puts "#{bin}#{plural}\t#{histogram[bin]}\t#{graph}" - end -end - -def print_footer - puts %Q{\n#{occasional_author_percentage}% of contributors are "occasional" (with <= #{OCCASIONAL_CUTOFF} commits)} - puts "\n#{onetime_author_percentage}% of contributors commit only once" - puts "\n#{extant_occasional_cask_percentage}% - #{historic_occasional_cask_percentage}% of Casks depend on an occasional contributor" - puts "\n#{extant_nonmaintainer_cask_percentage}% - #{historic_nonmaintainer_cask_percentage}% of Casks depend on a contributor who is not a maintainer" - puts "\n" -end - -def generate_report - print_header - print_table - print_footer -end - -### -### main -### - -cd_to_project_root -generate_report