Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

89 lines · 3.5 KBRaw History
1#!/usr/bin/env bash
2# Installs the Diffinery extension into the editors built on VS Code on this computer (Linux and macOS):
3#
4# curl -fsSL https://diffinery.com/install-editor | bash # every editor found
5# curl -fsSL https://diffinery.com/install-editor | bash -s -- cursor # only the ones named
6#
7# Names: code, code-insiders, cursor, windsurf, codium. Each editor's command-line tool is used from
8# PATH, or from its usual place in /Applications on macOS. The .vsix comes from the server that served
9# this script and is checked against the SHA-256 it publishes. The extension updates itself afterwards.
10# Served by Diffinery from apps/vscode/install/.
11if [ -z "${BASH_VERSION:-}" ]; then
12 echo "This installer needs bash: curl -fsSL __DIFFINERY_URL__/install-editor | bash" >&2
13 exit 1
14fi
15set -euo pipefail
16
17server=${DIFFINERY_URL:-__DIFFINERY_URL__}
18case $server in __*) server=https://diffinery.com ;; esac
19server=${server%/}
20
21if [ -t 2 ] && [ -z "${NO_COLOR:-}" ]; then
22 bold=$'\033[1m' dim=$'\033[2m' green=$'\033[32m' red=$'\033[31m' reset=$'\033[0m'
23else
24 bold='' dim='' green='' red='' reset=''
25fi
26say() { printf '%s\n' "$*" >&2; }
27die() {
28 say "${red}error${reset}: $*"
29 exit 1
30}
31command -v curl >/dev/null || die "curl is required"
32
33# name|label|macOS app bundle
34known="code|VS Code|Visual Studio Code
35code-insiders|VS Code Insiders|Visual Studio Code - Insiders
36cursor|Cursor|Cursor
37windsurf|Windsurf|Windsurf
38codium|VSCodium|VSCodium"
39
40find_cli() {
41 local name=$1 app=$2
42 if command -v "$name" >/dev/null 2>&1; then
43 command -v "$name"
44 return
45 fi
46 for base in "/Applications" "$HOME/Applications"; do
47 local p="$base/$app.app/Contents/Resources/app/bin/$name"
48 if [ -x "$p" ]; then
49 printf '%s\n' "$p"
50 return
51 fi
52 done
53 return 1
54}
55
56wanted=" $* "
57tmp=$(mktemp -d)
58trap 'rm -rf "$tmp"' EXIT
59meta=$(curl -fsSL "$server/-/vscode/version.json") || die "couldn't reach $server"
60version=$(printf '%s' "$meta" | sed -n 's/.*"version":"\([^"]*\)".*/\1/p')
61sha=$(printf '%s' "$meta" | sed -n 's/.*"sha256":"\([0-9a-f]*\)".*/\1/p')
62[ -n "$version" ] && [ -n "$sha" ] || die "unexpected answer from $server/-/vscode/version.json"
63vsix=$tmp/diffinery-$version.vsix
64curl -fsSL "$server/-/vscode/diffinery-$version.vsix" -o "$vsix" || die "downloading the extension failed"
65if command -v sha256sum >/dev/null; then got=$(sha256sum "$vsix" | cut -d' ' -f1); else got=$(shasum -a 256 "$vsix" | cut -d' ' -f1); fi
66[ "$got" = "$sha" ] || die "the download didn't match the published SHA-256; nothing was installed"
67
68installed=0
69while IFS='|' read -r name label app; do
70 if [ "$wanted" != " " ] && [[ $wanted != *" $name "* ]]; then continue; fi
71 cli=$(find_cli "$name" "$app") || {
72 [ "$wanted" != " " ] && say "${red}✗${reset} $label: its command-line tool ($name) wasn't found"
73 continue
74 }
75 if "$cli" --install-extension "$vsix" --force >/dev/null 2>"$tmp/err"; then
76 say "${green}✓${reset} $label: Diffinery extension $version installed"
77 installed=$((installed + 1))
78 else
79 say "${red}✗${reset} $label: $(tail -n 3 "$tmp/err")"
80 fi
81done <<<"$known"
82
83if [ "$installed" = 0 ]; then
84 say "No editor took the extension. Install it from the editor instead: Extensions → … → Install from VSIX…"
85 say "with ${bold}$server/-/vscode/diffinery.vsix${reset}, or see $server/docs/repositories/clone-in-your-editor"
86 exit 1
87fi
88say ""
89say "Next: in the editor, run ${bold}Git: Clone${reset} and pick ${bold}Clone from Diffinery${reset}. ${dim}($server/docs/repositories/clone-in-your-editor)${reset}"