Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions bash/bin/cask_report_bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env bash
# Dependencies: tail, head, grep, cat, git, ansifilter
# TODO
# 1. argument to prevent sha update

report() {
local type="$1"
local latest_sha_file="$HOME/.homebrew-${type}-latest-sha"
local cask_repo="/opt/homebrew/Library/Taps/homebrew/homebrew-${type}"
local version_regex='^[+-]\s*version\s+["\'""']?(.+?)["\'""']?$'
local homepage_regex='^\s+homepage\s+["\'""'](.+)["\'""']\s*$'
local -a updated added removed update_available

cd "$cask_repo" || return 1

local old_sha
if [[ -f "$latest_sha_file" ]]; then
old_sha=$(<"$latest_sha_file")
else
old_sha=$(git log | head -20 | /usr/bin/tail -r | head -1 | ansifilter | sed -nE 's/([a-z0-9]{7})\s.+/\1/p')
fi
local latest_sha
latest_sha=$(git log | head -1 | ansifilter | sed -nE 's/([a-z0-9]{7,})\s.+/\1/p')

mapfile -t installed_casks < <(brew list --cask)
local changes
changes=$(git diff --name-status "$old_sha" | grep Casks/ | ansifilter)

while IFS=$'\t' read -r status path; do
[[ -z "$path" ]] && continue
local app
app=$(sed -nE 's/^Casks\/(.+)\.rb$/\1/p' <<<"$path")
[[ -z "$app" ]] && continue

if [[ "$status" == 'D' ]]; then
removed+=("\033[94m${app}\033[0m")
else
local h homepage
h=$(cat "Casks/${app}.rb" | grep -E '^\s+homepage')
if [[ -z "$h" ]]; then
homepage=""
else
homepage=$(sed -nE "${homepage_regex}" <<<"$h" | sed -nE 's/'"$homepage_regex"'/\1/p')
fi
if [[ "$status" == 'A' ]]; then
added+=("\033[94m${app}\033[0m [\033[92m${homepage}\033[0m]")
elif [[ "$status" == 'M' ]]; then
local version_diff last_version current_version
version_diff=$(git diff "$old_sha" "Casks/${app}.rb" | grep -E '^[+-]\s+version')
if [[ -n "$version_diff" ]]; then
last_version=$(sed -n 1p <<<"$version_diff" | sed -nE 's/'"$version_regex"'/\1/p')
current_version=$(sed -n 2p <<<"$version_diff" | sed -nE 's/'"$version_regex"'/\1/p')
fi
local needs_update=""
if [[ -n "$version_diff" ]]; then
if printf '%s\n' "${installed_casks[@]}" | grep -qx "$app"; then
needs_update=1
update_available+=("✨ \033[32m${app}\033[0m")
fi
fi
updated+=("\033[94m${app}\033[0m${needs_update:+✨} [\033[92m${homepage}\033[0m]${version_diff:+ \${last_version} \033[33m<\033[0m \${current_version}}")
fi
fi
done <<<"$changes"

echo -e "\n\033[35m🔮 ${type^^}\033[0m"
if ((${#updated[@]})); then
echo -e "\033[95mUPDATED\033[0m"
printf '%s\n' "${updated[@]}"
fi
if ((${#added[@]})); then
echo -e "\033[95mADDED\033[0m"
printf '%s\n' "${added[@]}"
fi
if ((${#removed[@]})); then
echo -e "\033[95mREMOVED\033[0m"
printf '%s\n' "${removed[@]}"
fi
if ((${#update_available[@]})); then
echo -e "\033[95mOUTDATED\033[0m"
printf '%s\n' "${update_available[@]}"
fi
echo -e "\033[90mOld SHA: ${old_sha} New SHA: ${latest_sha}\033[0m"

printf '%s' "$latest_sha" >"$latest_sha_file"
}

report cask
110 changes: 110 additions & 0 deletions bash/bin/cask_report_nodejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env node
// Dependencies: tail, head, grep, cat, git, ansifilter
// TODO
// 1. argument to prevent sha update

const fs = require('fs');
const os = require('os');
const { execSync } = require('child_process');

function color(code, str) {
return `\u001b[${code}m${str}\u001b[0m`;
}

function report(type) {
const latestShaFile = `${os.homedir()}/.homebrew-${type}-latest-sha`;
const caskRepo = `/opt/homebrew/Library/Taps/homebrew/homebrew-${type}`;
const versionRegex = /^[+-]\s*version\s+['"]?(.+?)['"]?$/;
const homepageRegex = /^\s+homepage\s+["'](.+)["']\s*$/;
const updated = [];
const added = [];
const removed = [];
const updateAvailable = [];

process.chdir(caskRepo);

let oldSha;
if (fs.existsSync(latestShaFile)) {
oldSha = fs.readFileSync(latestShaFile, 'utf8').trim();
} else {
const output = execSync('git log | head -20 | /usr/bin/tail -r | head -1 | ansifilter', { encoding: 'utf8' });
const m = output.match(/([a-z0-9]{7})\s.+/);
oldSha = m ? m[1] : '';
}
const latestShaOutput = execSync('git log | head -1 | ansifilter', { encoding: 'utf8' });
const latestShaMatch = latestShaOutput.match(/([a-z0-9]{7,})\s.+/);
const latestSha = latestShaMatch ? latestShaMatch[1] : '';

const installedCasks = execSync('brew list --cask', { encoding: 'utf8' }).trim().split('\n');
const changes = execSync(`git diff --name-status ${oldSha} | grep Casks/ | ansifilter`, { encoding: 'utf8' }).trim().split('\n');

const apps = changes.map(c => {
const [status, path] = c.split('\t');
const m = path.match(/^Casks\/(.+)\.rb$/);
return m ? { status, name: m[1] } : null;
}).filter(Boolean);

apps.forEach(a => {
if (a.status === 'D') {
removed.push(color('94', a.name));
} else {
const h = execSync(`cat Casks/${a.name}.rb | grep -E '^\\s+homepage'`, { encoding: 'utf8' });
const homepageMatch = h.match(homepageRegex);
const homepage = homepageMatch ? homepageMatch[1] : '';
if (a.status === 'A') {
added.push(`${color('94', a.name)} [${color('92', homepage)}]`);
} else if (a.status === 'M') {
let versionDiff = '';
try {
versionDiff = execSync(`git diff ${oldSha} Casks/${a.name}.rb | grep -E '^[+-]\\s+version'`, { encoding: 'utf8' });
} catch {}
let lastVersion, currentVersion;
if (versionDiff) {
[lastVersion, currentVersion] = versionDiff.split('\n');
if (lastVersion) {
const lm = lastVersion.match(versionRegex);
lastVersion = lm ? lm[1] : undefined;
}
if (currentVersion) {
const cm = currentVersion.match(versionRegex);
currentVersion = cm ? cm[1] : undefined;
}
}
let needsUpdate = false;
if (versionDiff && installedCasks.includes(a.name)) {
needsUpdate = true;
updateAvailable.push(`✨ ${color('32', a.name)}`);
}
updated.push([
color('94', a.name),
needsUpdate ? '✨' : '',
` [${color('92', homepage)}]`,
versionDiff ? ` ${lastVersion} ${color('33', '<')} ${currentVersion}` : ''
].join(''));
}
}
});

console.log(`\n${color('35', '🔮 ' + type.toUpperCase())}`);
if (updated.length) {
console.log(color('95', 'UPDATED'));
console.log(updated.join('\n'));
}
if (added.length) {
console.log(color('95', 'ADDED'));
console.log(added.join('\n'));
}
if (removed.length) {
console.log(color('95', 'REMOVED'));
console.log(removed.join('\n'));
}
if (updateAvailable.length) {
console.log(color('95', 'OUTDATED'));
console.log(updateAvailable.join('\n'));
}
console.log(color('90', `Old SHA: ${oldSha} New SHA: ${latestSha}`));

fs.writeFileSync(latestShaFile, latestSha);
}

report('cask');