Merge pull request #758 from reitermarkus/cask-dev-scripts

Remove Cask developer scripts.
This commit is contained in:
Mike McQuaid 2016-08-19 22:01:24 +01:00 committed by GitHub
commit 7395ff2001
32 changed files with 0 additions and 3414 deletions

View File

@ -1,9 +0,0 @@
Before writing your issue, check our instructions for [reporting bugs](https://github.com/caskroom/homebrew-cask#reporting-bugs) or [making requests](https://github.com/caskroom/homebrew-cask#requests), as appropriate. Those will walk you through the process.
If none of those is appropriate, then **delete all this pre-inserted template text** and tell us your issue in as much detail as possible.
Please note that if it is apparent you ignored the instructions for reporting issues, your issue may be closed without review. When the guide isnt followed we get the same issues over and over. Having to repeatedly deal with the same solved and documented problems leads to maintainer burnout and a lot of wasted hours that could instead have been spent improving Homebrew-Cask itself and fixing real bugs.
If the guide itself was unclear, open *first* an issue or pull request stating what you found was confusing *and only then* your other issue.
Thank you for taking the time to make a correct report.

View File

@ -1,27 +0,0 @@
##### Instructions
- Look for and complete the section relevant to your submission. Delete the others, including these `Instructions`.
- `{{cask_file}}` represents the cask file youre submitting/editing (if applicable).
- If theres a checkbox you cant complete for any reason, thats OK. Just explain in detail why you werent able to do so.
### Changes to a cask
#### Editing an existing cask
- [ ] Commit message includes casks name (and new version, if applicable).
- [ ] `brew cask audit --download {{cask_file}}` is error-free.
- [ ] `brew cask style --fix {{cask_file}}` left no offenses.
#### Adding a new cask
- [ ] Checked there arent open [pull requests](https://github.com/caskroom/homebrew-cask/pulls) for the same cask.
- [ ] Checked there arent closed [issues](https://github.com/caskroom/homebrew-cask/issues) where that cask was already refused.
- [ ] When naming the cask, followed the [token reference](https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/token_reference.md).
- [ ] Commit message includes casks name.
- [ ] `brew cask audit --download {{cask_file}}` is error-free.
- [ ] `brew cask style --fix {{cask_file}}` left no offenses.
- [ ] `brew cask install {{cask_file}}` worked successfully.
- [ ] `brew cask uninstall {{cask_file}}` worked successfully.
### Changes to the core
- [ ] Followed [hacking.md](https://github.com/caskroom/homebrew-cask/blob/master/doc/development/hacking.md).

View File

@ -1,57 +0,0 @@
language: ruby
sudo: false
env:
global:
- LANG=en_US.UTF-8
- LANGUAGE=en_US.UTF-8
- LC_ALL=en_US.UTF-8
matrix:
include:
- env: OSX=10.11 HOMEBREW_RUBY=2.0.0
os: osx
osx_image: xcode7.3
rvm: system
- env: OSX=10.10 HOMEBREW_RUBY=2.0.0
os: osx
osx_image: xcode7.1
rvm: system
fast_finish: true
branches:
only:
- master
cache:
directories:
- $HOME/.gem
before_install:
- . ci/travis/before_install.sh
install:
- . ci/travis/install.sh
before_script:
- . ci/travis/before_script.sh
script:
- . ci/travis/script.sh
notifications:
email: false
irc:
channels:
- "chat.freenode.net#homebrew-cask"
template:
- "(%{repository_name}) %{build_number}: %{branch}@%{commit} %{author} -> %{message} %{build_url}"
use_notice: true
skip_join: true
webhooks:
urls:
- "https://webhooks.gitter.im/e/712d699360b239db14a5"
on_success: change
on_failure: always
on_start: never

View File

@ -1,190 +0,0 @@
#!/bin/bash
set -o pipefail
readonly program="$(basename "$0")"
skip_curl_verify=0
verbose=0
syntax_error() {
echo "$program: $1" >&2
echo "Try \`$program --help\` for more information." >&2
exit 1
}
depends_on() {
formula="$1"
[[ "$#" -eq 2 ]] && cmd="$2" || cmd=$(basename "${formula}")
if [[ ! $(which ${cmd}) ]]; then
echo -e "$(tput setaf 1)
This script depends on '${cmd}'.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install ${formula}'.
$(tput sgr0)" | sed -E 's/ {6}//' >&2
exit 1
fi
}
depends_on 'tsparber/tiny-scripts/curl-check-url'
usage() {
echo "
This script changes the url, appcast and homepage stanzas to https
After changing to https a HTTP GET request is performed to verify if the url is reachable.
If the https url is not reachable it is reverted to the previous version.
Known Issues: If multiple url/appcast stanzas are present, all urls are changed but only
those for the current os are verified.
If no cask name is given the current work directory is scanned with the given options.
usage: $program [options] [<cask_name>]
options:
-s, --skip-verify Skip checking for a HTTP 200 Status Code using curl.
--verbose Show more verbose output.
-h, --help Show this help.
Based on: https://github.com/vitorgalvao/tiny-scripts/blob/master/cask-repair
" | sed -E 's/^ {4}//'
}
# available flags
while [[ "$1" ]]; do
case "$1" in
-h | --help)
usage
exit 0
;;
-s | --skip-verify)
skip_curl_verify=1
;;
--verbose)
verbose=1
;;
-*)
syntax_error "unrecognized option: $1"
;;
*)
break
;;
esac
shift
done
# define function to check if given URL exists and is reachable using HTTPS
check_url_for_https() {
cask_url="$1"
verbose_option=""
[[ ${verbose} -ne 0 ]] && verbose_option="-v "
# check if the URL sends a 200 HTTP code, else abort
curl-check-url ${verbose_option} "${cask_url}" > /dev/null
exit_code=$?
if [[ exit_code -ne 0 ]]; then
echo "curl returned ${exit_code}: FAIL for ${cask_url}"
return 1
fi
return 0
}
# define function to modify part of stanza
replace_protocol_of_stanza() {
cask_file="$1"
stanza="$2"
old_value="$3"
new_value="$4"
sed "s|${stanza} \(['\"]\)${old_value}://|${stanza} \1${new_value}://|g" "${cask_file}" > tmpfile
mv tmpfile "${cask_file}"
}
# define abort function, that will reset the state
finish() {
# show message
if [[ "$1" == 'abort' ]]; then
echo -e "$(tput setaf 1)$2$(tput sgr0)\n"
[[ ! -z "${cask_file}" ]] && git checkout -- "${cask_file}"
exit 1
elif [[ "$1" == 'success' ]]; then
echo -e "$(tput setaf 2)Updated: ${cask_name} is now using HTTPS$(tput sgr0)\n"
exit 0
fi
}
# cleanup if aborted with ⌃C
trap 'finish abort "You aborted"' SIGINT
# exit if not inside a 'homebrew-*/Casks' directory
casks_dir=$(pwd | perl -ne 'print m{homebrew-[^/]+/Casks}')
if [[ -z "${casks_dir}" ]]; then
echo -e "\n$(tput setaf 1)You need to be inside a '/homebrew-*/Casks' directory$(tput sgr0)\n"
exit 1
fi
# exit if no argument was given: Run in current directory
if [[ -z "$1" ]]; then
options=""
[[ ${skip_curl_verify} -ne 0 ]] && options+=" --skip-verify"
[[ ${verbose} -ne 0 ]] && options+=" --verbose"
for file in *.rb;
do
"$0" ${options} ${file}
done
exit 0
fi
# clean the cask's name, and check if it is valid
cask_name="$1"
[[ "${cask_name}" == *'.rb' ]] && cask_name=$(echo "${cask_name}" | sed 's|\.rb$||')
cask_file="./${cask_name}.rb"
[[ ! -f "${cask_file}" ]] && finish abort 'There is no such cask'
# initial tasks
git checkout -- "${cask_file}"
# check if a http url exists
cask_contains_http=$(grep "['\"]http://" "${cask_file}")
if [[ -z ${cask_contains_http} ]]; then
echo -e "Skipped ${cask_name} no http found\n"
exit 0
fi
updated_stanzas=0
for stanza in url appcast homepage; do
# Check if the stanza exists
stanza_contained=$(grep "${stanza} ['\"]" "${cask_file}")
[[ -z ${stanza_contained} ]] && continue
stanza_contains_https=$(grep "${stanza} ['\"]http://" "${cask_file}")
if [[ -z ${stanza_contains_https} ]]; then
# echo "Skipped stanza ${stanza} in ${cask_name} no http url found"
continue
fi
replace_protocol_of_stanza ${cask_file} ${stanza} "http" "https"
if [[ ${skip_curl_verify} -eq 0 ]]; then
check_url_for_https $(brew cask _stanza ${stanza} "${cask_name}")
else
true
fi
if [[ $? -ne 0 ]]; then
echo "Restored original value for stanza ${stanza} as curl check failed"
replace_protocol_of_stanza ${cask_file} ${stanza} "https" "http"
else
updated_stanzas=$((updated_stanzas+1))
fi
done
if [[ ${updated_stanzas} -ne 0 ]]; then
finish success
else
finish abort "no updated stanzas after verify for ${cask_name}"
fi

View File

@ -1,199 +0,0 @@
#!/bin/bash
#
# develop_brew_cask
#
# Called via symlink as:
# production_brew_cask
#
called_as="$(basename "$0")"
###
### 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
###
taps_subdir="Library/Taps"
cask_tap_subdir="caskroom/homebrew-cask"
dev_links=("cmd" "lib" "Casks")
###
### 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 git_root
script_dir="$(/usr/bin/dirname "$0")"
cd "$script_dir"
git_root="$(git rev-parse --show-toplevel)"
if [[ -z "$git_root" ]]; then
die "ERROR: Could not find git project root"
fi
cd "$git_root"
}
cd_to_tap_dir () {
local taps_dir="$1"
local tap_dir="$2"
if [[ ! -d "$tap_dir" ]]; then
die "ERROR: Could not find tap dir under $taps_dir/"
fi
cd "$tap_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 () {
for link_name in "${dev_links[@]}"; do
remove_dev_link "$link_name"
done
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"
}
create_dev_links () {
local git_root="$1"
for link_name in "${dev_links[@]}"; do
create_dev_link "$git_root" "$link_name"
done
printf "brew-cask is now in development mode\n"
printf "Note: it is not safe to run 'brew update' while in development mode\n"
}
remove_dev_link () {
local link_name="$1"
/bin/rm -- "$link_name"
/bin/mv -- "production_$link_name" "$link_name"
}
create_dev_link () {
local git_root="$1"
local link_name="$2"
/bin/mv -- "$link_name" "production_$link_name"
/bin/ln -s -- "$git_root/$link_name" .
}
###
### main
###
_develop_brew_cask_develop_action () {
die "brew-cask is already set up for development"
}
_develop_brew_cask_production_action () {
create_dev_links "$git_root"
}
_production_brew_cask_develop_action () {
remove_dev_links
}
_production_brew_cask_production_action () {
die "brew-cask is already set up for production"
}
_main () {
local git_root brew_repository taps_dir tap_dir
# initialization
cd_to_project_root
git_root="$(/bin/pwd)"
brew_repository="$(brew --repository)"
taps_dir="$brew_repository/$taps_subdir"
tap_dir="$taps_dir/$cask_tap_subdir"
# sanity check
not_inside_homebrew "$tap_dir" "$git_root"
# action
cd_to_tap_dir "$taps_dir" "$tap_dir"
if [[ -e "production_lib" ]]; then
eval "_${called_as}_develop_action"
else
eval "_${called_as}_production_action"
fi
}
_develop_brew_cask_usage () {
printf "develop_brew_cask
Symlink private repo directories into Homebrew's Cellar, so
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.
You can reverse this operation with 'production_brew_cask'.
Note: it is not safe to run 'brew update' while development
mode is in effect.
"
}
_production_brew_cask_usage () {
printf "production_brew_cask
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',
unless you are using similar scripts to create symlinks into
other Caskroom development repos.
"
}
# ensure we're called by a valid name
case "${called_as}" in
develop_brew_cask) ;;
production_brew_cask) ;;
*)
die "ERROR: name ${called_as} not recognized"
;;
esac
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
eval "_${called_as}_usage"
exit
fi
# dispatch main
_main "${@}"
#

View File

@ -1,121 +0,0 @@
#!/bin/bash
readonly caskroom_online='https://github.com/caskroom'
readonly caskroom_repos_dir='/tmp/caskroom_repos'
readonly caskroom_repos=(homebrew-cask homebrew-versions homebrew-fonts homebrew-eid)
readonly curl_flags=(--silent --location --header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36')
inaccessible_appcasts=()
if [[ ! $(which 'ghi') ]] || ! security find-internet-password -s github.com -l 'ghi token' &> /dev/null; then
echo -e "$(tput setaf 1)
This script requires 'ghi' installed and configured.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install ghi'.
To configure it, run 'ghi config --auth <username>'. Your Github password will be required, but is never stored.
$(tput sgr0)" | sed -E 's/ {4}//' >&2
exit 1
fi
function message {
echo "${1}"
}
function go_to_repos_dir {
[[ ! -d "${caskroom_repos_dir}" ]] && mkdir -p "${caskroom_repos_dir}"
cd "${caskroom_repos_dir}" || exit 1
}
function go_to_repo_and_update {
local repo_name repo_dir casks_dir
repo_name="${1}"
repo_dir="${caskroom_repos_dir}/${repo_name}"
casks_dir="${repo_dir}/Casks"
if [[ ! -d "${repo_dir}" ]]; then
go_to_repos_dir
message "Cloning ${repo_name}…"
git clone "https://github.com/caskroom/${repo_name}.git" --quiet
cd "${casks_dir}" || exit 1
else
cd "${casks_dir}" || exit 1
message "Updating ${repo_name}…"
git pull --rebase origin master --quiet
fi
}
function open_issue {
local repo_name cask_name cask_url version appcast_url issue_number
repo_name="${1}"
cask_name="${2}"
cask_url="${caskroom_online}/${repo_name}/blob/master/Casks/${cask_name}.rb"
version="${3}"
appcast_url="${4}"
message="$(echo "Outdated cask: ${cask_name}
Outdated cask: [\`${cask_name}\`](${cask_url}).
Info:
+ version: \`${version}\`.
+ appcast url: ${appcast_url}.
" | sed -E 's/^ {4}//')"
issue_number=$(ghi open --label 'outdated appcast' --message "${message}" | head -1 | perl -pe 's/^#(\d+): .*/\1/')
message "Opened issue: https://github.com/caskroom/${repo_name}/issues/${issue_number}."
}
function is_appcast_available {
local appcast_url
appcast_url="${1}"
http_status="$(curl "${curl_flags[@]}" --head --write-out '%{http_code}' "${appcast_url}" -o '/dev/null')"
[[ "${http_status}" == 200 ]]
}
function report_outdated_appcasts {
local repo_name cask_name appcast_url current_checkpoint new_checkpoint version
repo_name="${1}"
for cask_file in ./*; do
appcast_url="$(brew cask _stanza appcast "${cask_file}")"
[[ -z "${appcast_url}" ]] && continue # skip early if there is no appcast
cask_name="$(basename "${cask_file%.*}")"
message "Verifying appcast checkpoint for ${cask_name}…"
if is_appcast_available "${appcast_url}"; then
current_checkpoint="$(brew cask _stanza --yaml appcast "${cask_file}" | grep '^- :checkpoint' | awk '{print $3}')"
new_checkpoint="$(curl "${curl_flags[@]}" --compressed "${appcast_url}" | sed 's|<pubDate>[^<]*</pubDate>||g' | shasum --algorithm 256 | awk '{ print $1 }')"
else
message "There was an error checking the appcast for ${cask_name}."
inaccessible_appcasts+=("${repo_name}/${cask_name}")
continue
fi
if [[ "${current_checkpoint}" != "${new_checkpoint}" ]]; then
version="$(brew cask _stanza version "${cask_file}")"
message "${cask_name} is outdated. Opening issue in ${repo_name}…"
open_issue "${repo_name}" "${cask_name}" "${version}" "${appcast_url}"
fi
done
}
for repo in "${caskroom_repos[@]}"; do
go_to_repo_and_update "${repo}"
report_outdated_appcasts "${repo}"
done
if [[ ${#inaccessible_appcasts[@]} -gt 0 ]];then
echo # empty line
message 'Some casks have appcasts that errored out, and may need to be rechecked:'
printf '%s\n' "${inaccessible_appcasts[@]}"
fi

View File

@ -1,68 +0,0 @@
#!/bin/bash
readonly user_agent=(--user-agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36')
usage() {
local program exit_status
program="$(basename "$0")"
exit_status="$1"
echo "usage: ${program} <path_to_app>"
exit "${exit_status}"
}
absolute_path() {
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
appcast_found_error() {
local error_reason="$1"
echo "An appcast was found pointing to ${appcast_url}, but it ${error_reason}. You should:
1. Check your internet connection.
2. Try again later.
3. Contact the developer."
exit 1
}
# exit if no argument (or more than one) was given
if [[ -z "$1" ]] || [[ -n "$2" ]]; then
usage 1
fi
# get plist
path_to_app="$(absolute_path "$1")"
path_to_plist="${path_to_app}/Contents/Info.plist"
if [[ ! -f "${path_to_plist}" ]]; then
echo 'You need to use this on a .app bundle. Please verify your target.'
usage 1
fi
# get appcast
appcast_url="$(defaults read "${path_to_plist}" 'SUFeedURL' 2>/dev/null)"
if [[ -z "${appcast_url}" ]]; then
echo 'It appears this app does not have a Sparkle appcast'
exit 0
fi
# validate appcast
appcast_http_response="$(curl --silent --head "${user_agent[@]}" --write-out '%{http_code}' "${appcast_url}" -o /dev/null)"
[[ "${appcast_http_response}" != '200' ]] && appcast_found_error "returned a non-200 (OK) HTTP response code (${appcast_http_response})"
appcast_checkpoint=$(curl --silent --compressed --location "${user_agent[@]}" "${appcast_url}" | sed 's|<pubDate>[^<]*</pubDate>||g' | shasum --algorithm 256 | awk '{ print $1 }')
[[ "${appcast_checkpoint}" == 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' ]] && appcast_found_error 'seems to be empty'
# output appcast
echo "A Sparkle appcast was found. You should add it to your cask as
appcast '${appcast_url}',
checkpoint: '${appcast_checkpoint}'
You should likely also add 'auto_updates true'"
exit 0

View File

@ -1,78 +0,0 @@
#!/bin/bash
IFS=$'\n'
readonly caskroom_repos_dir='/tmp/caskroom_repos'
readonly caskroom_repos=(homebrew-cask homebrew-versions homebrew-fonts homebrew-eid)
if [[ ! $(which 'ghi') ]] || ! security find-internet-password -s github.com -l 'ghi token' &> /dev/null; then
echo -e "$(tput setaf 1)
This script requires 'ghi' installed and configured.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install ghi'.
To configure it, run 'ghi config --auth <username>'. Your Github password will be required, but is never stored.
$(tput sgr0)" | sed -E 's/ {4}//' >&2
exit 1
fi
if [[ ! $(which 'cask-repair') ]]; then
echo -e "$(tput setaf 1)
This script requires 'cask-repair'.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install vitorgalvao/tiny-scripts/cask-repair'.
$(tput sgr0)" | sed -E 's/ {4}//' >&2
exit 1
fi
function message {
echo "${1}"
}
function go_to_repos_dir {
[[ ! -d "${caskroom_repos_dir}" ]] && mkdir -p "${caskroom_repos_dir}"
cd "${caskroom_repos_dir}" || exit 1
}
function go_to_repo_and_update {
local repo_name repo_dir casks_dir
repo_name="${1}"
repo_dir="${caskroom_repos_dir}/${repo_name}"
casks_dir="${repo_dir}/Casks"
if [[ ! -d "${repo_dir}" ]]; then
go_to_repos_dir
message "Cloning ${repo_name}…"
git clone "https://github.com/caskroom/${repo_name}.git" --quiet
cd "${casks_dir}" || exit 1
else
cd "${casks_dir}" || exit 1
message "Updating ${repo_name}…"
git pull --rebase origin master --quiet
fi
}
function fix_outdated_appcasts {
local issue_number cask_name pr_number
for line in $(ghi list --state open --no-pulls --label 'outdated appcast' --reverse | tail +2); do
[[ "${line}" == 'None.' ]] && break # exit early if there are no relevant issues in repo
issue_number="$(awk '{print $1}' <<< "${line}")"
cask_name="$(awk '{print $4}' <<< "${line}")"
cask-repair --pull origin --push origin --open-appcast --closes-issue "${issue_number}" --blind-submit "${cask_name}"
if [[ "$?" -eq 0 ]]; then
pr_number="$(ghi list --pulls --creator | sed -n 2p | awk '{print $1}')"
ghi edit --label 'outdated appcast' "${pr_number}" &>/dev/null
ghi comment --close --message "Closing in favour of #${pr_number}." "${issue_number}" &>/dev/null
fi
done
}
for repo in "${caskroom_repos[@]}"; do
go_to_repo_and_update "${repo}"
fix_outdated_appcasts
done

View File

@ -1,418 +0,0 @@
#!/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby
#
# generate_cask_token
#
# todo:
#
# remove Ruby 2.0 dependency and change shebang line
#
# detect Cask files which differ only by the placement of hyphens.
#
# merge entirely into "brew cask create" command
#
###
### dependencies
###
require "pathname"
require "open3"
begin
# not available by default
require "active_support/inflector"
rescue LoadError
end
###
### configurable constants
###
EXPANDED_SYMBOLS = {
"+" => "plus",
"@" => "at",
}.freeze
CASK_FILE_EXTENSION = ".rb".freeze
# Hardcode App names that cannot be transformed automatically.
# Example: in "x48.app", "x48" is not a version number.
# The value in the hash should be a valid Cask token.
APP_EXCEPTION_PATS = {
# looks like a trailing version, but is not.
%r{\Aiterm\Z}i => "iterm2",
%r{\Aiterm2\Z}i => "iterm2",
%r{\Apgadmin3\Z}i => "pgadmin3",
%r{\Ax48\Z}i => "x48",
%r{\Avitamin-r[\s\d\.]*\Z}i => "vitamin-r",
%r{\Aimagealpha\Z}i => "imagealpha",
# upstream is in the midst of changing branding
%r{\Abitcoin-?qt\Z}i => "bitcoin-core",
# "mac" cannot be separated from the name because it is in an English phrase
%r{\Aplayonmac\Z}i => "playonmac",
%r{\Acleanmymac[\s\d\.]*\Z}i => "cleanmymac",
# arguably we should not have kept these two exceptions
%r{\Akismac\Z}i => "kismac",
%r{\Avoicemac\Z}i => "voicemac",
}.freeze
# Preserve trailing patterns on App names that could be mistaken
# for version numbers, etc
PRESERVE_TRAILING_PATS = [
%r{id3}i,
%r{mp3}i,
%r{3[\s-]*d}i,
%r{diff3}i,
%r{\A[^\d]+\+\Z}i,
].freeze
# The code that employs these patterns against App names
# - hacks a \b (word-break) between CamelCase and snake_case transitions
# - anchors the pattern to end-of-string
# - applies the patterns repeatedly until there is no match
REMOVE_TRAILING_PATS = [
# spaces
%r{\s+}i,
# generic terms
%r{\bapp}i,
%r{\b(?:quick[\s-]*)?launcher}i,
# "mac", "for mac", "for OS X", "macOS", "for macOS".
%r{\b(?:for)?[\s-]*mac(?:intosh|OS)?}i,
%r{\b(?:for)?[\s-]*os[\s-]*x}i,
# hardware designations such as "for x86", "32-bit", "ppc"
%r{(?:\bfor\s*)?x.?86}i,
%r{(?:\bfor\s*)?\bppc}i,
%r{(?:\bfor\s*)?\d+.?bits?}i,
# frameworks
%r{\b(?:for)?[\s-]*(?:oracle|apple|sun)*[\s-]*(?:jvm|java|jre)}i,
%r{\bgtk}i,
%r{\bqt}i,
%r{\bwx}i,
%r{\bcocoa}i,
# localizations
%r{en\s*-\s*us}i,
# version numbers
%r{[^a-z0-9]+}i,
%r{\b(?:version|alpha|beta|gamma|release|release.?candidate)(?:[\s\.\d-]*\d[\s\.\d-]*)?}i,
%r{\b(?:v|ver|vsn|r|rc)[\s\.\d-]*\d[\s\.\d-]*}i,
%r{\d+(?:[a-z\.]\d+)*}i,
%r{\b\d+\s*[a-z]}i,
%r{\d+\s*[a-c]}i, # constrained to a-c b/c of false positives
].freeze
# Patterns which are permitted (undisturbed) following an interior version number
AFTER_INTERIOR_VERSION_PATS = [
%r{ce}i,
%r{pro}i,
%r{professional}i,
%r{client}i,
%r{server}i,
%r{host}i,
%r{viewer}i,
%r{launcher}i,
%r{installer}i,
].freeze
###
### classes
###
class AppName < String
def self.remove_trailing_pat
@@remove_trailing_pat ||= %r{(?<=.)(?:#{REMOVE_TRAILING_PATS.join('|')})\Z}i
end
def self.preserve_trailing_pat
@@preserve_trailing_pat ||= %r{(?:#{PRESERVE_TRAILING_PATS.join('|')})\Z}i
end
def self.after_interior_version_pat
@@after_interior_version_pat ||= %r{(?:#{AFTER_INTERIOR_VERSION_PATS.join('|')})}i
end
def english_from_app_bundle
return self if ascii_only?
return self unless File.exist?(self)
# check Info.plist CFBundleDisplayName
bundle_name = Open3.popen3(*%w[
/usr/libexec/PlistBuddy -c
],
"Print CFBundleDisplayName",
Pathname.new(self).join("Contents", "Info.plist").to_s) do |_stdin, stdout, _stderr|
begin
stdout.gets.force_encoding("UTF-8").chomp
rescue
end
end
return AppName.new(bundle_name) if bundle_name && bundle_name.ascii_only?
# check Info.plist CFBundleName
bundle_name = Open3.popen3(*%w[
/usr/libexec/PlistBuddy -c
],
"Print CFBundleName",
Pathname.new(self).join("Contents", "Info.plist").to_s) do |_stdin, stdout, _stderr|
begin
stdout.gets.force_encoding("UTF-8").chomp
rescue
end
end
return AppName.new(bundle_name) if bundle_name && bundle_name.ascii_only?
# check localization strings
local_strings_file = Pathname.new(self).join("Contents", "Resources", "en.lproj", "InfoPlist.strings")
local_strings_file = Pathname.new(self).join("Contents", "Resources", "English.lproj", "InfoPlist.strings") unless local_strings_file.exist?
if local_strings_file.exist?
bundle_name = File.open(local_strings_file, "r:UTF-16LE:UTF-8") do |fh|
%r{\ACFBundle(?:Display)?Name\s*=\s*"(.*)";\Z}.match(fh.readlines.grep(%r{^CFBundle(?:Display)?Name\s*=\s*}).first) do |match|
match.captures.first
end
end
return AppName.new(bundle_name) if bundle_name && bundle_name.ascii_only?
end
# check Info.plist CFBundleExecutable
bundle_name = Open3.popen3(*%w[
/usr/libexec/PlistBuddy -c
],
"Print CFBundleExecutable",
Pathname.new(self).join("Contents", "Info.plist").to_s) do |_stdin, stdout, _stderr|
begin
stdout.gets.force_encoding("UTF-8").chomp
rescue
end
end
return AppName.new(bundle_name) if bundle_name && bundle_name.ascii_only?
self
end
def basename
if Pathname.new(self).exist?
AppName.new(Pathname.new(self).basename.to_s)
else
self
end
end
def remove_extension
sub(%r{\.app\Z}i, "")
end
def decompose_to_ascii
# crudely (and incorrectly) decompose extended latin characters to ASCII
return self if ascii_only?
return self unless respond_to?(:mb_chars)
AppName.new(mb_chars.normalize(:kd).each_char.select(&:ascii_only?).join)
end
def hardcoded_exception
APP_EXCEPTION_PATS.each do |regexp, exception|
return AppName.new(exception) if regexp.match(self)
end
nil
end
def insert_vertical_tabs_for_camel_case
app_name = AppName.new(self)
if app_name.sub!(%r{(#{self.class.preserve_trailing_pat})\Z}i, "")
trailing = Regexp.last_match(1)
end
app_name.gsub!(%r{([^A-Z])([A-Z])}, "\\1\v\\2")
app_name.sub!(%r{\Z}, trailing) if trailing
app_name
end
def insert_vertical_tabs_for_snake_case
gsub(%r{_}, "\v")
end
def clean_up_vertical_tabs
gsub(%r{\v}, "")
end
def remove_interior_versions!
# done separately from REMOVE_TRAILING_PATS because this
# requires a substitution with a backreference
sub!(%r{(?<=.)[\.\d]+(#{self.class.after_interior_version_pat})\Z}i, '\1')
sub!(%r{(?<=.)[\s\.\d-]*\d[\s\.\d-]*(#{self.class.after_interior_version_pat})\Z}i, '-\1')
end
def remove_trailing_strings_and_versions
app_name = insert_vertical_tabs_for_camel_case
.insert_vertical_tabs_for_snake_case
while self.class.remove_trailing_pat.match(app_name) &&
!self.class.preserve_trailing_pat.match(app_name)
app_name.sub!(self.class.remove_trailing_pat, "")
end
app_name.remove_interior_versions!
app_name.clean_up_vertical_tabs
end
def simplified
return @simplified if @simplified
@simplified = english_from_app_bundle
.basename
.decompose_to_ascii
.remove_extension
@simplified = @simplified.hardcoded_exception || @simplified.remove_trailing_strings_and_versions
@simplified
end
end
class CaskFileName < String
def spaces_to_hyphens
gsub(%r{ +}, "-")
end
def delete_invalid_chars
gsub(%r{[^a-z0-9-]+}, "")
end
def collapse_multiple_hyphens
gsub(%r{--+}, "-")
end
def delete_leading_hyphens
gsub(%r{^--+}, "")
end
def delete_hyphens_before_numbers
gsub(%r{-([0-9])}, '\1')
end
def spell_out_symbols
cask_file_name = self
EXPANDED_SYMBOLS.each do |k, v|
cask_file_name.gsub!(k, " #{v} ")
end
cask_file_name.sub(%r{ +\Z}, "")
end
def add_extension
sub(%r{(?:#{escaped_cask_file_extension})?\Z}i, CASK_FILE_EXTENSION)
end
def remove_extension
sub(%r{#{escaped_cask_file_extension}\Z}i, "")
end
def from_simplified_app_name
return @from_simplified_app_name if @from_simplified_app_name
@from_simplified_app_name = if APP_EXCEPTION_PATS.rassoc(remove_extension)
remove_extension
else
remove_extension
.downcase
.spell_out_symbols
.spaces_to_hyphens
.delete_invalid_chars
.collapse_multiple_hyphens
.delete_leading_hyphens
.delete_hyphens_before_numbers
end
raise "Could not determine Simplified App name" if @from_simplified_app_name.empty?
@from_simplified_app_name.add_extension
end
end
###
### methods
###
def 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
Pathname.new(stdout.gets.chomp)
rescue
raise "could not find project root"
end
end
raise "could not find project root" unless @git_root.exist?
@git_root
end
def escaped_cask_file_extension
@escaped_cask_file_extension ||= Regexp.escape(CASK_FILE_EXTENSION)
end
def simplified_app_name
@simplified_app_name ||= AppName.new(ARGV.first.dup.force_encoding("UTF-8")).simplified
end
def cask_file_name
@cask_file_name ||= CaskFileName.new(simplified_app_name).from_simplified_app_name
end
def cask_token
@cask_token ||= cask_file_name.remove_extension
end
def warnings
return @warnings if @warnings
@warnings = []
unless APP_EXCEPTION_PATS.rassoc(cask_token)
if %r{\d} =~ cask_token
@warnings.push "WARNING: '#{cask_token}' contains digits. Digits which are version numbers should be removed."
end
end
filename = project_root.join("Casks", cask_file_name)
if filename.exist?
@warnings.push "WARNING: the file '#{filename}' already exists. Prepend the vendor name if this is not a duplicate."
end
@warnings
end
def report
puts "Proposed Simplified App name: #{simplified_app_name}" if $debug
puts "Proposed token: #{cask_token}"
puts "Proposed file name: #{cask_file_name}"
puts "Cask Header Line: cask '#{cask_token}' do"
unless warnings.empty?
$stderr.puts "\n"
$stderr.puts warnings
$stderr.puts "\n"
exit 1
end
end
###
### main
###
usage = <<-EOS
Usage: generate_cask_token [ -debug ] <application.app>
Given an Application name or a path to an Application, propose a
Cask token, filename, and header line.
With -debug, also provide the internal "Simplified App Name".
EOS
if ARGV.first =~ %r{^-+h(elp)?$}i
puts usage
exit 0
end
if ARGV.first =~ %r{^-+debug?$}i
$debug = 1
ARGV.shift
end
unless ARGV.length == 1
puts usage
exit 1
end
report

View File

@ -1,74 +0,0 @@
#!/usr/bin/env ruby
#
# generate_issue_template_urls
#
###
### dependencies
###
require "erb"
###
### constants
###
BASE_URL = "https://github.com/caskroom/homebrew-cask/issues/new".freeze
###
### methods
###
def main(args)
args.each do |file|
File.read(file).scan(%r{(.*?)\n(.*)}m) do |title, body|
puts generate_url(title, body)
end
end
end
def generate_url(title, body)
encoded_title = url_encode(title)
encoded_body = url_encode(body)
if $debug
puts "Encoded title: #{encoded_title}"
puts "Encoded body: #{encoded_body}"
end
"#{BASE_URL}?title=#{encoded_title}&body=#{encoded_body}"
end
def url_encode(unencoded_str)
ERB::Util.url_encode(unencoded_str)
end
###
### main
###
usage = <<-EOS
Usage: generate_issue_template_urls <issue_template.md> ...
Given one or more GitHub issue template files, generate encoded URLs for each
and print, separated by newlines. The first line of a template file should be
the issue title.
With -debug, print out the encoded title and body individually as well.
EOS
if ARGV.first =~ %r{^-+h(elp)?$}i
puts usage
exit 0
end
if ARGV.first =~ %r{^-+debug?$}i
$debug = 1
ARGV.shift
end
if ARGV.empty?
puts usage
exit 1
end
main(ARGV)

View File

@ -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 <dir>
Find irregular whitespace in Cask files within <dir>
"
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 "${@:-}"
#

View File

@ -1,166 +0,0 @@
#!/bin/bash
#
# list_apps_in_pkg
#
###
### 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
###
opt_lax=''
opt_pkg=''
pkgdir=''
# 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
}
app_source_1 () {
/usr/bin/find "$pkgdir" -name PackageInfo -print0 | \
"$xargs" -0 /usr/bin/perl -0777 -ne \
'while (m{<pkg-info[^\n]*install-location="/Applications".*?path\s*=\s*"([^"]+)"}sg) { my $p = $1; $p =~ s{\A.*/}{}; print "$p\n" }';
}
app_source_2 () {
/usr/bin/find "$pkgdir" -name PackageInfo -print0 | \
"$xargs" -0 /usr/bin/perl -0777 -ne \
'while (m{<pkg-info[^\n]*install-location="/".*?path\s*=\s*"./Applications/([^"]+)"}sg) { my $p = $1; $p =~ s{\A.*/}{}; print "$p\n" }';
}
app_source_3 () {
/usr/bin/find "$pkgdir" -type d -name '*.app' | \
perl -pe 's{\A.*/}{}';
}
app_source_4 () {
/usr/bin/find "$pkgdir" -name PackageInfo -print0 | \
"$xargs" -0 /usr/bin/perl -0777 -ne \
'while (m{path\s*=\s*"([^"]+\.app)"}sg) { my $p = $1; $p =~ s{\A.*/}{}; print "$p\n" }';
}
app_source_5 () {
/usr/bin/find "$pkgdir" -name Archive.pax.gz -print0 | \
"$xargs" -0 -n1 -I{} /bin/bash -c \
"/usr/bin/gunzip -c '{}' | /bin/pax | /usr/bin/egrep '\.app'" | \
/usr/bin/perl -pe 's{\A.*/([^/]+\.app).*\Z}{$1}';
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
'printf "{}"; /bin/test -n "$(/usr/bin/find /Applications -type d -maxdepth 3 -name "{}" -print0; /usr/bin/find ~/Applications -type d -maxdepth 3 -name "{}")" && printf " (+)"; printf "\n"'
}
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 ] <file.pkg>
Given a package file, extract a list of candidate App names from
inside the pkg, which may be useful for naming a Cask.
The given package file need not be installed.
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.
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
See CONTRIBUTING.md and 'man pkgutil' for more information.
"
exit
elif [[ $arg =~ ^-+lax$ ]]; then
opt_lax='true'
elif [[ "$arg" = "$opt_pkg" ]]; then
true
else
die "ERROR: Unknown argument '$arg'"
fi
done
if [[ -h "$opt_pkg" ]]; then
opt_pkg="$(/usr/bin/readlink "$opt_pkg")"
fi
if ! [[ -e "$opt_pkg" ]]; then
die "ERROR: No such pkg file: '$opt_pkg'"
fi
}
###
### main
###
_list_apps_in_pkg () {
if [[ -d "$opt_pkg" ]]; then
pkgdir="$opt_pkg"
else
local tmpdir="$(/usr/bin/mktemp -d -t list_ids_in_pkg)"
trap "/bin/rm -rf -- '$tmpdir'" EXIT
pkgdir="$tmpdir/unpack"
/usr/sbin/pkgutil --expand "$opt_pkg" "$tmpdir/unpack" "$pkgdir"
fi
{
# 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;
app_source_5;
fi
} | \
merge_sources | \
mark_up_sources
}
process_args "${@}"
# dispatch main
_list_apps_in_pkg
#

View File

@ -1,93 +0,0 @@
#!/bin/bash
#
# list_id_in_kext
#
###
### 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
###
kextdir=''
# prefer GNU xargs
xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')"
###
### functions
###
bundle_id_source_1 () {
/usr/bin/find "$kextdir" -name Info.plist -print0 | \
"$xargs" -0 -I {} /usr/libexec/PlistBuddy {} -c 'Print :CFBundleIdentifier'
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/egrep -v '^com\.apple\.'
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
'printf "{}"; /bin/test "$(/usr/sbin/kextstat -kl -b "{}" | /usr/bin/wc -l)" -gt 0 && printf " (+)"; printf "\n"'
}
###
### main
###
_list_id_in_kext () {
kextdir="$1"
if [[ -h "$kextdir" ]]; then
kextdir="$(/usr/bin/readlink "$kextdir")"
fi
{
# emit strings that look like bundle ids
bundle_id_source_1;
} | \
clean_sources | \
merge_sources | \
mark_up_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then
printf "list_id_in_kext <file.kext>
Given a Kernel Extension (kext) bundle dir on disk, extract the
associated kext Bundle ID, which may be useful in a Cask uninstall
stanza, eg
uninstall :kext => 'kext.id.goes.here'
The kext need not be loaded for this script to work.
If a given kext is currently loaded, it will be followed by a plus
symbol '(+)' in the output. This can be verified via the command
/usr/sbin/kextstat -kl -b 'kext.id.goes.here'
See CONTRIBUTING.md and 'man kextstat' for more information.
"
exit
fi
# dispatch main
_list_id_in_kext "${@}"
#

View File

@ -1,162 +0,0 @@
#!/bin/bash
#
# list_ids_in_app
#
###
### 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
###
appdir=''
scriptdir="$(dirname "$0")"
# prefer GNU xargs
xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')"
###
### functions
###
bundle_id_source_1 () {
/usr/bin/find "$appdir" -name Info.plist -print0 | \
"$xargs" -0 -I {} /usr/libexec/PlistBuddy {} -c 'Print :CFBundleIdentifier'
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/egrep -v '^com\.apple\.' | \
/usr/bin/egrep -vi '^org\.andymatuschak\.Sparkle' | \
/usr/bin/egrep -vi '^(SDL|SDL_net|TDParseKit)$' | \
/usr/bin/egrep -vi '^com\.growl\.(growlframework|WebKit|iCal|GrowlAction|GrowlLauncher|GrowlPlugins)' | \
/usr/bin/egrep -vi '^com\.adobe\.(ACE|AGM|AXE8SharedExpat|AdobeExtendScript|AdobeScCore|AdobeXMPCore|BIB|BIBUtils|CoolType|ESD\.AdobeUpdaterLibFramework|JP2K|adobe_caps|AcrobatPlugin|AdobeResourceSynchronizer|ICUConverter|ICUData|acrobat\.assert|acrobat\.pdfviewerNPAPI|adobepdf417pmp|ahclientframework|datamatrixpmp|eulaframework|framework|linguistic|qrcodepmp)' | \
/usr/bin/egrep -vi '^com\.microsoft\.(Automator|certificate\.framework|chart|converterlib|converters|excel\.pde|grammar|igx|mcp|merp|msls3|netlib|officeart|ole|oleo|powerplant|powerplantcore|powerpoint\.pde|speller|thesaurus|urlmon|wizard|wordforms|MSCommon|mbuinstrument_framework|mbukernel_framework|rdpkit)' | \
/usr/bin/egrep -vi '^com\.google\.(Chrome\.framework|Chrome\.helper|Keystone|BreakpadFramework|GDataFramework|Reporter)' | \
/usr/bin/egrep -vi '^atmo\.mac\.macho' | \
/usr/bin/egrep -vi '^com\.3dconnexion\.driver\.client' | \
/usr/bin/egrep -vi '^com\.Breakpad\.crash_report_sender' | \
/usr/bin/egrep -vi '^com\.Cycling74\.driver\.Soundflower' | \
/usr/bin/egrep -vi '^com\.HumbleDaisy\.HDCrashReporter' | \
/usr/bin/egrep -vi '^com\.amazon\.JSONKit' | \
/usr/bin/egrep -vi '^com\.bensyverson\..*dvmatte' | \
/usr/bin/egrep -vi '^com\.binarymethod\.BGHUDAppKit' | \
/usr/bin/egrep -vi '^com\.blacktree\.(QSCore|QSEffects|QSFoundation|QSInterface)' | \
/usr/bin/egrep -vi '^com\.brandonwalkin\.BWToolkitFramework' | \
/usr/bin/egrep -vi '^com\.cruzapp\.TDWebThumbnail' | \
/usr/bin/egrep -vi '^com\.cycling74\.QTExportTool' | \
/usr/bin/egrep -vi '^com\.fluidapp\.(BrowserBrowserPlugIn|FluidInstance|ThumbnailPlugIn)' | \
/usr/bin/egrep -vi '^com\.github\.ObjectiveGit' | \
/usr/bin/egrep -vi '^com\.heroku\.RedisAdapter' | \
/usr/bin/egrep -vi '^com\.instinctivecode\.MGScopeBar' | \
/usr/bin/egrep -vi '^com\.intel\.nw\.helper' | \
/usr/bin/egrep -vi '^com\.joshaber\.RockemSockem' | \
/usr/bin/egrep -vi '^com\.katidev\.KTUIKit' | \
/usr/bin/egrep -vi '^com\.kirin\.plugin\.adapter' | \
/usr/bin/egrep -vi '^com\.lextek\.onix' | \
/usr/bin/egrep -vi '^com\.macromedia\.(Flash Player\.authplaylib|PepperFlashPlayer)' | \
/usr/bin/egrep -vi '^com\.mainconcept\.mc\.enc\.avc' | \
/usr/bin/egrep -vi '^com\.netscape\.(DefaultPlugin|MRJPlugin)' | \
/usr/bin/egrep -vi '^com\.nxtbgthng\.JSONKit' | \
/usr/bin/egrep -vi '^com\.omnigroup\.(OmniAppKit|OmniInspector|framework)' | \
/usr/bin/egrep -vi '^com\.oracle\.java\..*\.jdk' | \
/usr/bin/egrep -vi '^com\.panic\.(PanicCore|automator|CodaScriptPlugIn)' | \
/usr/bin/egrep -vi '^com\.pixelespresso\.cocoafob' | \
/usr/bin/egrep -vi '^com\.positivespinmedia\.(PSMTabBarControlFramework|PSMTabBarFramework)' | \
/usr/bin/egrep -vi '^com\.softube\.(Amplifier|Cabinet)' | \
/usr/bin/egrep -vi '^com\.sonic\.(AS_Storage|AuthorScriptHDMV)' | \
/usr/bin/egrep -vi '^com\.soundcloud\.Share-on-SoundCloud' | \
/usr/bin/egrep -vi '^com\.stuffit\.(format|sdk|stuffitcore)' | \
/usr/bin/egrep -vi '^com\.sun\.Scintilla' | \
/usr/bin/egrep -vi '^com\.yourcompany' | \
/usr/bin/egrep -vi '^coop\.plausible\.(CrashReporter|PLWeakCompatibility)' | \
/usr/bin/egrep -vi '^de\.buzzworks\.Quincy' | \
/usr/bin/egrep -vi '^de\.dstoecker\.xadmaster' | \
/usr/bin/egrep -vi '^isao\.sonobe\.OgreKit' | \
/usr/bin/egrep -vi '^jp\.hmdt\.framework\.hmdtblkappkit' | \
/usr/bin/egrep -vi '^net\.hockeyapp\.sdk\.mac' | \
/usr/bin/egrep -vi '^net\.java\.openjdk\.jre' | \
/usr/bin/egrep -vi '^net\.liquidx\.EyeTunes' | \
/usr/bin/egrep -vi '^net\.sourceforge\.Log4Cocoa' | \
/usr/bin/egrep -vi '^net\.sourceforge\.munt\.MT32Emu' | \
/usr/bin/egrep -vi '^net\.sourceforge\.skim-app\.framework' | \
/usr/bin/egrep -vi '^net\.wafflesoftware\.ShortcutRecorder\.framework' | \
/usr/bin/egrep -vi '^org\.AFNetworking\.AFNetworking' | \
/usr/bin/egrep -vi '^org\.boredzo\.(LMX|ISO8601DateFormatter)' | \
/usr/bin/egrep -vi '^org\.dribin\.dave\.DDHidLib' | \
/usr/bin/egrep -vi '^org\.linkbackproject\.LinkBack' | \
/usr/bin/egrep -vi '^org\.mozilla\.(crashreporter|plugincontainer|universalchardet|updater)' | \
/usr/bin/egrep -vi '^org\.python\.(python|PythonLauncher|buildapplet)' | \
/usr/bin/egrep -vi '^org\.remotesensing\.libtiff' | \
/usr/bin/egrep -vi '^org\.vafer\.FeedbackReporter' | \
/usr/bin/egrep -vi '^org\.xiph\.(ogg|vorbis)' | \
/usr/bin/egrep -vi '^se\.propellerheads\..*\.library$'
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
"printf '{}'; $scriptdir/list_running_app_ids -t '{}' >/dev/null 2>&1 && printf ' (+)'; printf "\\\\n""
}
###
### main
###
_list_ids_in_app () {
appdir="$1"
if [[ -h "$appdir" ]]; then
appdir="$(/usr/bin/readlink "$appdir")"
fi
{
# emit strings that look like bundle ids
bundle_id_source_1;
} | \
clean_sources | \
merge_sources | \
mark_up_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then
printf "list_ids_in_app <path.app>
Given a Application (app) bundle directory on disk, extract the
associated app Bundle ID, which may be useful in a Cask uninstall
stanza, eg
uninstall quit: 'app.id.goes.here'
The app need not be running for this script to work.
Bundle IDs attributed to Apple and common developer frameworks
are excluded from the output.
If a given app is currently running, it will be followed by a plus
symbol '(+)' in the output. This can be verified via the command
list_running_app_ids | grep 'app.id.goes.here'
See CONTRIBUTING.md for more information.
"
exit
fi
# dispatch main
_list_ids_in_app "${@}"
#

View File

@ -1,115 +0,0 @@
#!/bin/bash
#
# list_ids_in_pkg
#
###
### 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
###
pkgdir=''
# prefer GNU xargs
xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')"
###
### functions
###
bundle_id_source_1 () {
/usr/bin/find "$pkgdir" -name PackageInfo -print0 | \
"$xargs" -0 /usr/bin/perl -0777 -ne \
'while (m{<pkg-info.*?\sid(?:entifier)?\s*=\s*"([^"]*?)"}sg) { print "$1\n" }'
}
bundle_id_source_2 () {
/usr/bin/find "$pkgdir" -name Info.plist -print0 | \
"$xargs" -0 -I {} /usr/libexec/PlistBuddy {} -c 'Print :CFBundleIdentifier'
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/egrep -v '^com\.apple\.' | \
/usr/bin/egrep -v 'sparkle\.finish-installation$'
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
'printf "{}"; /usr/sbin/pkgutil --pkg-info "{}" >/dev/null 2>&1 && printf " (+)"; printf "\n"'
}
###
### main
###
_list_ids_in_pkg () {
if [[ -d "$1" ]]; then
pkgdir="$1"
if [[ -h "$pkgdir" ]]; then
pkgdir="$(/usr/bin/readlink "$pkgdir")"
fi
else
local tmpdir="$(/usr/bin/mktemp -d -t list_ids_in_pkg)"
trap "/bin/rm -rf -- '$tmpdir'" EXIT
pkgdir="$tmpdir/unpack"
/usr/sbin/pkgutil --expand "$1" "$tmpdir/unpack" "$pkgdir"
fi
{
# emit strings that look like bundle ids
bundle_id_source_1;
bundle_id_source_2;
} | \
merge_sources | \
clean_sources | \
mark_up_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then
printf "list_ids_in_pkg <file.pkg>
Given a package file, extract a list of candidate Package IDs
which may be useful in a Cask uninstall stanza, eg
uninstall pkgutil: 'package.id.goes.here'
The given package file need not be installed.
The output of this script should be overly inclusive -- not
every candidate package id in the output will be needed at
uninstall time.
Package IDs designated by Apple or common development frameworks
will be excluded from the output.
If a package id is already installed, it will be followed by
a plus symbol '(+)' in the output. This can be verified via
the command
/usr/sbin/pkgutil --pkg-info 'package.id.goes.here'
See CONTRIBUTING.md and 'man pkgutil' for more information.
"
exit
fi
# dispatch main
_list_ids_in_pkg "${@}"
#

View File

@ -1,90 +0,0 @@
#!/bin/bash
#
# list_installed_launchjob_ids
#
###
### 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
###
# prefer GNU xargs
xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')"
###
### functions
###
launchjob_id_source_1 () {
/usr/bin/find ~/Library/LaunchAgents/ \
~/Library/LaunchDaemons/ \
/Library/LaunchAgents/ \
/Library/LaunchDaemons/ \
-type f -print0 2>/dev/null | \
"$xargs" -0 /usr/bin/perl -0777 -ne \
'while (m{<key>\s*Label\s*</key>\s*<string>([^<]+?)</string>}sg) { print "$1\n" }'
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/egrep -v '^com\.apple\.'
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
'printf "{}"; /bin/launchctl list "{}" >/dev/null 2>&1 && printf " (+)"; printf "\n"'
}
###
### main
###
_list_installed_launchjob_ids () {
{
launchjob_id_source_1;
} | \
merge_sources | \
clean_sources | \
mark_up_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
printf "list_installed_launchjob_ids
List all installed launchjob IDs, which may be useful
in a Cask uninstall stanza, eg
uninstall launchctl: 'job.id.goes.here'
Launchctl jobs attributed to Apple will be ommitted.
If a launchctl job is currently loaded, and visible to the current
user, it will be followed by a plus symbol '(+)' in the output.
This can be verified via the command
/bin/launchctl list 'job.id.goes.here'
See CONTRIBUTING.md and 'man launchctl' for more information.
"
exit
fi
# dispatch main
_list_installed_launchjob_ids "${@}"
#

View File

@ -1,45 +0,0 @@
#!/bin/bash
#
# list_loaded_kext_ids
#
###
### 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\.'
}
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
printf "list_loaded_kext_ids
Print Bundle IDs for currently loaded Kernel Extensions (kexts)
which may be useful in a Cask uninstall stanza, eg
uninstall kext: 'kext.bundle.id.goes.here'
Kexts attributed to Apple are excluded from the output.
See CONTRIBUTING.md for more information.
"
exit
fi
# dispatch main
_list_loaded_kext_ids "${@}"
#

View File

@ -1,84 +0,0 @@
#!/bin/bash
#
# list_loaded_launchjob_ids
#
###
### 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
###
###
### functions
###
launchjob_id_source_1 () {
if [[ "$EUID" -ne 0 ]]; then
/usr/bin/sudo -p 'Optionally give your sudo password: ' -- /bin/launchctl list | /usr/bin/cut -f3
fi
}
launchjob_id_source_2 () {
/bin/launchctl list | /usr/bin/cut -f3
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/egrep -v '^Label$' | \
/usr/bin/egrep -v '^com\.apple\.' | \
/usr/bin/egrep -v '^0x[0-9a-f]+\.anonymous\.' | \
/usr/bin/egrep -v '^\[0x' | \
/usr/bin/egrep -v '\.[0-9]+$'
}
###
### main
###
_list_loaded_launchjob_ids () {
{
launchjob_id_source_1;
launchjob_id_source_2;
} | \
clean_sources | \
merge_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
printf "list_loaded_launchjob_ids
List IDs for currently-loaded launchctl jobs, which may be useful
in a Cask uninstall stanza, eg
uninstall launchctl: 'job.id.goes.here'
If this command is not run as the superuser, you will be prompted
for a password to run a subcommand using 'sudo'. The password is
not required, but supplying it may reveal additional job ids. To
skip using the password, press <return> repeatedly.
Launchctl jobs attributed to Apple are excluded from the output.
See CONTRIBUTING.md and 'man launchctl' for more information.
"
exit
fi
# dispatch main
_list_loaded_launchjob_ids "${@}"
#

View File

@ -1,64 +0,0 @@
#!/usr/bin/env ruby
#
# list_login_items_for_app
#
###
### dependencies
###
require "open3"
###
### methods
###
def usage
<<-EOS
Usage: list_login_items_for_app <path.app>
Given an Application (app) bundle directory on disk, find all
login items associated with that app, which you can use in a
Cask uninstall stanza, eg
uninstall login_item: 'login item name'
Note that you will likely need to have opened the app at least
once for any login items to be present.
See CONTRIBUTING.md for more information.
EOS
end
def process_args
if ARGV.first =~ %r{^-+h(?:elp)?$}
puts usage
exit 0
elsif ARGV.length == 1
$app_path = ARGV.first
else
puts usage
exit 1
end
end
def list_login_items_for_app(app_path)
out, err, status = Open3.capture3(
"/usr/bin/osascript", "-e",
"tell application \"System Events\" to get the name of every login item " \
"whose path contains \"#{File.basename(app_path)}\""
)
if status.exitstatus > 0
$stderr.puts err
exit status.exitstatus
end
puts out.gsub(", ", "\n")
end
###
### main
###
process_args
list_login_items_for_app $app_path

View File

@ -1,126 +0,0 @@
#!/bin/bash
#
# list_payload_in_pkg
#
###
### 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
###
pkg_arg=''
tmp_boms=''
# prefer GNU xargs
xargs="$(/usr/bin/which gxargs || printf '/usr/bin/xargs')"
trap cleanup_tmp_boms EXIT
###
### functions
###
cleanup_tmp_boms () {
if [[ -n "$tmp_boms" ]]; then
# tmpfile ensures that rmdir -p is not too destructive
local tmpfile="/tmp/list_payload_in_pkg.$$";
/usr/bin/touch "$tmpfile";
echo "$tmp_boms" | \
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 /bin/rm -f --;
{
echo "$tmp_boms" | \
/usr/bin/perl -pe 's{[^/]+\n}{\000}sg' | \
"$xargs" -0 /bin/rmdir -p -- || true
} 2>/dev/null
/bin/rm -- "$tmpfile";
fi
}
bom_source_1 () {
/usr/bin/find "$pkg_arg" -iname '*.pkg' -print0 | \
"$xargs" -0 -I{} -n1 /usr/sbin/pkgutil --bom "{}" 2>/dev/null
}
bom_source_2 () {
/usr/bin/find "$pkg_arg" -name '*.bom'
}
expand_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 lsbom --
}
merge_sources () {
/usr/bin/sort | /usr/bin/uniq
}
clean_sources () {
/usr/bin/cut -f1 | \
/usr/bin/perl -pe 's{\A\.}{}' | \
/usr/bin/egrep '.'
}
mark_up_sources () {
/usr/bin/perl -pe 's{\n}{\000}sg' | \
"$xargs" -0 -I{} -n1 /bin/bash -c \
'printf "{}"; /bin/test -e "{}" >/dev/null 2>&1 && printf " (+)"; printf "\n"'
}
###
### main
###
_list_payload_in_pkg () {
pkg_arg="$1"
if [[ -h "$pkg_arg" ]]; then
pkg_arg="$(/usr/bin/readlink "$pkg_arg")"
fi
tmp_boms="$(bom_source_1)";
{
# find BOM files
echo "$tmp_boms";
bom_source_2;
} | \
expand_sources | \
clean_sources | \
merge_sources | \
mark_up_sources
}
# process args
if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then
printf "list_payload_in_pkg <file.pkg>
Given a package file, show what files may be installed by that
pkg, which may be useful when writing a Cask uninstall stanza.
The given package file need not be installed.
The output attempts to be overly inclusive. However, since
pkg files are allowed to run arbitrary scripts, there can be
no guarantee that the output is exact.
If a given file is already installed, it will be followed by
a plus symbol '(+)' in the output.
See CONTRIBUTING.md and 'man pkgutil' for more information.
"
exit
fi
# dispatch main
_list_payload_in_pkg "${@}"
#

View File

@ -1,83 +0,0 @@
#!/bin/bash
#
# list_pkg_ids_by_regexp
#
###
### settings
###
set -e # exit on any uncaught error
set +o histexpand # don't expand history expressions
shopt -s nocasematch # case-insensitive regular expressions
###
### 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
}
fail_informatively () {
local message="No match."
if ! [[ "$1" =~ '*' ]]; then
message="$message Suggestion: try '${1}.*'"
fi
die "$message"
}
analyze_regexp () {
if [[ "$1" =~ ^\^ ]]; then
warn "Note: pkgutil regular expressions are implicitly anchored with '^' at start"
fi
if [[ "$1" =~ \$$ ]]; then
warn "Note: pkgutil regular expressions are implicitly anchored with '$' at end"
fi
}
###
### main
###
_list_pkg_ids_by_regexp () {
analyze_regexp "$1"
if ! /usr/sbin/pkgutil --pkgs="$1"; then
fail_informatively "$1"
fi
}
# process args
if [[ $1 =~ ^-+h(elp)?$ || $# -ne 1 ]]; then
printf "list_pkg_ids_by_regexp <regexp>
Print pkg receipt IDs for installed packages matching a regular
expression, which may be useful in a Cask uninstall stanza, eg
uninstall pkgutil: 'pkg.regexp.goes.here'
Unlike most other scripts in this directory, package IDs attributed to
Apple are NOT excluded from the output. This is to avoid uninstalling
essential system files due to an exuberant regexp.
For more information, see
https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/uninstall.md
"
exit
fi
# dispatch main
_list_pkg_ids_by_regexp "${@}"
#

View File

@ -1,46 +0,0 @@
#!/bin/bash
#
# list_recent_pkg_ids
#
###
### 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 | \
/usr/bin/egrep '\.plist$' | \
/usr/bin/perl -pe 's{\A([^/]+)\.plist\Z}{$1}sg' | \
/usr/bin/egrep -v '^com\.apple\.' | \
/usr/bin/head -10
}
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
printf "list_recent_pkg_ids
Print pkg receipt IDs for the 10 most-recently-installed packages,
which may be useful in a Cask uninstall stanza, eg
uninstall pkgutil: 'pkg.receipt.id.goes.here'
Package IDs attributed to Apple are excluded from the output.
See CONTRIBUTING.md for more information.
"
exit
fi
# dispatch main
_list_recent_pkg_ids "${@}"
#

View File

@ -1,115 +0,0 @@
#!/usr/bin/env ruby
#
# list_running_app_ids
#
###
### dependencies
###
require "open3"
require "set"
###
### globals
###
$opt_test = nil
###
### methods
###
def check_ruby
if RUBY_VERSION.to_f < 2.0
print "You are currently using Ruby ", RUBY_VERSION, ", but version 2.0 or above is required."
exit 1
end
end
def usage
<<-EOS
list_running_app_ids [ -t <bundle-id> ]
Print a list of currently running Applications and associated
Bundle IDs, which may be useful in a Cask uninstall stanza, eg
uninstall quit: 'bundle.id.goes.here'
Applications attributed to Apple are excluded from the output.
With optional "-t <bundle-id>", silently test if a given app
is running, exiting with an error code if not.
See CONTRIBUTING.md for more information.
EOS
end
def process_args
until ARGV.empty?
if ARGV.first =~ %r{^-+t(?:est)?$} && ARGV.length > 1
ARGV.shift
$opt_test = ARGV.shift
elsif ARGV.first =~ %r{^-+h(?:elp)?$}
puts usage
exit 0
else
puts usage
exit 1
end
end
end
def load_apps
out, err, status = Open3.capture3("/usr/bin/osascript", "-e", 'tell application "System Events" to get (name, bundle identifier, unix id) of every process')
if status.exitstatus > 0
puts err
exit status.exitstatus
end
out = out.split(", ")
one_third = out.length / 3
@app_names = out.shift(one_third)
@bundle_ids = out.shift(one_third)
@unix_ids = out.shift(one_third)
end
def test_app(bundle)
@bundle_ids.include?(bundle) ? 0 : 1
end
def excluded_bundle_id(bundle_id)
%r{^com\.apple\.}.match(bundle_id)
end
def excluded_app_name(app_name)
%r{^osascript$}.match(app_name) # this script itself
end
def report_apps
running = Set.new
@app_names.zip(@bundle_ids, @unix_ids).each do |app_name, bundle_id, _unix_id|
next if excluded_bundle_id bundle_id
next if excluded_app_name app_name
bundle_id.gsub!(%r{^(missing value)$}, '<\1>')
running.add "#{bundle_id}\t#{app_name}"
end
puts "bundle_id\tapp_name\n"
puts "--------------------------------------\n"
puts running.to_a.sort
end
###
### main
###
check_ruby
process_args
load_apps
if $opt_test
exit test_app($opt_test)
else
report_apps
end

View File

@ -1,84 +0,0 @@
#!/bin/bash
#
# list_url_attributes_on_file
#
###
### 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
###
file_arg=''
attribute_1='com.apple.metadata:kMDItemWhereFroms'
###
### 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
}
xml_source_1 () {
if /usr/bin/xattr -p "$attribute_1" "$file_arg" > /dev/null 2>&1; then
/usr/bin/xattr -p "$attribute_1" "$file_arg" | /usr/bin/xxd -r -p | /usr/bin/plutil -convert xml1 -o - - 2> /dev/null
fi
}
extract_string_elements () {
/usr/bin/perl -ne 'print "$1\n" if m{\A\s*<\s*string\s*>(.+?)<\s*/\s*string\s*>\Z}'
}
###
### main
###
_list_url_attributes_on_file () {
file_arg="$1"
{
xml_source_1;
} | \
extract_string_elements
}
# process_args
if [[ $1 =~ ^-+h(elp)?$ || -z "$1" ]]; then
printf "list_url_attributes_on_file <file>
Given a downloaded file, extract possible sources from macOS extended
attributes, which may be useful in a Cask url stanza.
Currently the only attribute examined is
com.apple.metadata:kMDItemWhereFroms
This attribute will typically be set if the file was downloaded via a
browser, but not if the file was downloaded by a CLI utility such as
curl.
See CONTRIBUTING.md for more information.
"
exit
fi
# dispatch main
_list_url_attributes_on_file "${@}"
#

View File

@ -1,99 +0,0 @@
#!/bin/bash
IFS=$'\n'
readonly caskroom_online='https://github.com/caskroom'
readonly caskroom_repos_dir='/tmp/caskroom_repos'
readonly caskroom_repos=(homebrew-cask homebrew-versions homebrew-fonts homebrew-eid)
if [[ ! $(which 'ghi') ]] || ! security find-internet-password -s github.com -l 'ghi token' &> /dev/null; then
echo -e "$(tput setaf 1)
This script requires 'ghi' installed and configured.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install ghi'.
To configure it, run 'ghi config --auth <username>'. Your Github password will be required, but is never stored.
$(tput sgr0)" | sed -E 's/ {4}//' >&2
exit 1
fi
if [[ ! $(which 'fastmerge') ]]; then
echo -e "$(tput setaf 1)
This script requires 'fastmerge'.
If you have [Homebrew](http://brew.sh), you can install it with 'brew install vitorgalvao/tiny-scripts/fastmerge'.
$(tput sgr0)" | sed -E 's/ {4}//' >&2
exit 1
fi
function message {
echo "${1}"
}
function go_to_repos_dir {
[[ ! -d "${caskroom_repos_dir}" ]] && mkdir -p "${caskroom_repos_dir}"
cd "${caskroom_repos_dir}" || exit 1
}
function go_to_repo_and_update {
local repo_name repo_dir casks_dir
repo_name="${1}"
repo_dir="${caskroom_repos_dir}/${repo_name}"
casks_dir="${repo_dir}/Casks"
if [[ ! -d "${repo_dir}" ]]; then
go_to_repos_dir
message "Cloning ${repo_name}…"
git clone "https://github.com/caskroom/${repo_name}.git" --quiet
cd "${casks_dir}" || exit 1
else
cd "${casks_dir}" || exit 1
message "Updating ${repo_name}…"
git pull --rebase origin master --quiet
fi
}
function delete_current_branch {
local current_branch
current_branch="$(git rev-parse --abbrev-ref HEAD)"
git checkout master --quiet
git branch -D "${current_branch}" --quiet
}
function delete_cask_repair_branches {
[[ $(ghi list --state open --pulls --label 'outdated appcast' | tail -1) == 'None.' ]] && cask-repair --push origin --delete-branches
}
function merge_outdated_appcasts {
local repo_name pr_number cask_name pr_url last_commit
repo_name="${1}"
for line in $(ghi list --state open --pulls --label 'outdated appcast' --reverse | tail +2); do
[[ "${line}" == 'None.' ]] && break # exit early if there are no relevant issues in repo
pr_number="$(awk '{print $1}' <<< "${line}")"
cask_name="$(awk '{print $3}' <<< "${line}")"
pr_url="${caskroom_online}/${repo_name}/pull/${pr_number}"
hub checkout "${pr_url}" &>/dev/null
last_commit="$(git log -n 1 --pretty=format:'%H')"
delete_current_branch
if [[ "$(hub ci-status "${last_commit}")" == 'success' ]]; then
message "Merging pull request for ${cask_name}…"
fastmerge --maintainer --remote origin "${pr_url}"
else
continue
fi
done
}
for repo in "${caskroom_repos[@]}"; do
go_to_repo_and_update "${repo}"
merge_outdated_appcasts "${repo}"
delete_cask_repair_branches
git gc
done

View File

@ -1 +0,0 @@
develop_brew_cask

View File

@ -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 [ <commit-object> ]
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 "${@}"

View File

@ -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

View File

@ -1,106 +0,0 @@
#!/usr/bin/env bash
#
# update_issue_template_urls
#
###
### settings
###
set -e # exit on uncaught error
set +o histexpand # don't expand history expressions
shopt -s nocasematch # case-insensitive regular expressions
###
### constants
###
script_subdir='developer/bin'
template_subdir='doc/issue_templates'
generate_url_script='generate_issue_template_urls'
files_to_update=('README.md')
###
### 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
}
usage () {
printf "update_issue_template_urls
Regenerate issue template URLs and update them in relevant files.
Note: docs using issue template URLs must use a specific format.
If the template file is called 'bug_report.md', the URL must be
referenced in the doc as follows:
[Some link text][bug_report_template]
...
[bug_report_template]: (auto-generated-url)
"
}
cd_to_project_root () {
local script_dir git_root
script_dir="$(/usr/bin/dirname "$0")"
cd "$script_dir"
git_root="$(git rev-parse --show-toplevel)"
if [[ -z "$git_root" ]]; then
die "ERROR: Could not find git project root"
fi
cd "$git_root"
}
generate_template_url () {
local template_file="$1"
"$script_subdir/$generate_url_script" "$template_file"
}
update_template_url () {
local template_name="$1"
local template_url="$2"
local escaped_template_url="${template_url/&/\\&}"
/usr/bin/sed -i '' \
-e "s|^\\(\\[${template_name}_template\\]: \\).*$|\\1${escaped_template_url}|g" \
-- "${files_to_update[@]}"
}
###
### main
###
_update_issue_template_urls () {
local template_file template_name template_url
cd_to_project_root
for template_file in ./$template_subdir/*; do
template_name="${template_file##*/}"
template_name="${template_name%%.*}"
template_url="$(generate_template_url "$template_file")"
update_template_url "$template_name" "$template_url"
done
}
# process args
if [[ $1 =~ ^-+h(elp)?$ ]]; then
usage
exit
fi
# dispatch main
_update_issue_template_urls

View File

@ -1,43 +0,0 @@
#!/usr/bin/env ruby
#
# Generously contributed by Markus Doits
# https://github.com/doits
# (c) 2014 MIT license
#
require "rubygems"
class Hbc
def installed_version?
!installed_version.nil?
end
def installed_version
# returns latest installed version if possible
Pathname.glob(caskroom_path.join("*")).map(&:basename).sort do |x, y|
Gem::Version.new(x) <=> Gem::Version.new(y) # throws exception if invalid version is provided ...
end.last
rescue
nil
# ... return nil in this case
end
def update_available?
Gem::Version.correct?(version) && # we have something to compare against in Cask file ...
installed_version? && # ... we can determine current installed version ...
Gem::Version.new(installed_version) < Gem::Version.new(version) # ... compare
end
end
module Hbc::Scopes
module ClassMethods
def upgradable
Hbc.installed.select(&:update_available?)
end
end
end
upgradable_casks = Hbc.upgradable
puts upgradable_casks.empty? && "No outdated packages" || upgradable_casks

View File

@ -1,16 +0,0 @@
# brewcask-dumpcask
#
# A trivial `brew cask` external command, implemented in Ruby.
# Loads a Cask definition, then dumps it in YAML format.
# Example usage:
#
# brew cask dumpcask google-chrome
#
command_name = ARGV.shift
cask_token = ARGV.shift
cask = Hbc.load(cask_token)
Hbc.debug = true
cask.dumpcask

View File

@ -1,16 +0,0 @@
#!/bin/bash
#
# brewcask-showargs
#
# A trivial `brew cask` external command, implemented in bash.
# Displays the arguments passed to it. Example usage:
#
# brew cask showargs these were my args
#
set -e; # exit on uncaught error
set +o histexpand; # don't expand history expressions
echo "$@";
#