Merge pull request #758 from reitermarkus/cask-dev-scripts
Remove Cask developer scripts.
This commit is contained in:
commit
7395ff2001
@ -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 isn‘t 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.
|
@ -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 you’re submitting/editing (if applicable).
|
||||
- If there’s a checkbox you can’t complete for any reason, that’s OK. Just explain in detail why you weren’t able to do so.
|
||||
|
||||
### Changes to a cask
|
||||
#### Editing an existing cask
|
||||
|
||||
- [ ] Commit message includes cask’s 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 aren’t open [pull requests](https://github.com/caskroom/homebrew-cask/pulls) for the same cask.
|
||||
- [ ] Checked there aren’t 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 cask’s 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).
|
@ -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
|
@ -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
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
@ -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 "${@:-}"
|
||||
|
||||
#
|
@ -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
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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
|
@ -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 "${@}"
|
||||
|
||||
#
|
@ -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
|
@ -1 +0,0 @@
|
||||
develop_brew_cask
|
@ -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 "${@}"
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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 "$@";
|
||||
|
||||
#
|
Loading…
x
Reference in New Issue
Block a user