happy-stacks 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -74
- package/bin/happys.mjs +140 -9
- package/docs/edison.md +381 -0
- package/docs/happy-development.md +733 -0
- package/docs/menubar.md +54 -0
- package/docs/paths-and-env.md +141 -0
- package/docs/server-flavors.md +61 -2
- package/docs/stacks.md +55 -4
- package/extras/swiftbar/auth-login.sh +10 -7
- package/extras/swiftbar/git-cache-refresh.sh +130 -0
- package/extras/swiftbar/happy-stacks.5s.sh +175 -83
- package/extras/swiftbar/happys-term.sh +128 -0
- package/extras/swiftbar/happys.sh +35 -0
- package/extras/swiftbar/install.sh +99 -13
- package/extras/swiftbar/lib/git.sh +309 -1
- package/extras/swiftbar/lib/icons.sh +2 -2
- package/extras/swiftbar/lib/render.sh +279 -132
- package/extras/swiftbar/lib/system.sh +64 -10
- package/extras/swiftbar/lib/utils.sh +469 -10
- package/extras/swiftbar/pnpm-term.sh +2 -122
- package/extras/swiftbar/pnpm.sh +4 -14
- package/extras/swiftbar/set-interval.sh +10 -5
- package/extras/swiftbar/set-server-flavor.sh +19 -10
- package/extras/swiftbar/wt-pr.sh +10 -3
- package/package.json +2 -1
- package/scripts/auth.mjs +833 -14
- package/scripts/build.mjs +24 -4
- package/scripts/cli-link.mjs +3 -3
- package/scripts/completion.mjs +15 -8
- package/scripts/daemon.mjs +200 -23
- package/scripts/dev.mjs +230 -57
- package/scripts/doctor.mjs +26 -21
- package/scripts/edison.mjs +1828 -0
- package/scripts/happy.mjs +3 -7
- package/scripts/init.mjs +275 -46
- package/scripts/install.mjs +14 -8
- package/scripts/lint.mjs +145 -0
- package/scripts/menubar.mjs +81 -8
- package/scripts/migrate.mjs +302 -0
- package/scripts/mobile.mjs +59 -21
- package/scripts/run.mjs +222 -43
- package/scripts/self.mjs +3 -7
- package/scripts/server_flavor.mjs +3 -3
- package/scripts/service.mjs +190 -38
- package/scripts/setup.mjs +790 -0
- package/scripts/setup_pr.mjs +182 -0
- package/scripts/stack.mjs +2273 -92
- package/scripts/stop.mjs +160 -0
- package/scripts/tailscale.mjs +164 -23
- package/scripts/test.mjs +144 -0
- package/scripts/tui.mjs +556 -0
- package/scripts/typecheck.mjs +145 -0
- package/scripts/ui_gateway.mjs +248 -0
- package/scripts/uninstall.mjs +21 -13
- package/scripts/utils/auth_files.mjs +58 -0
- package/scripts/utils/auth_login_ux.mjs +76 -0
- package/scripts/utils/auth_sources.mjs +12 -0
- package/scripts/utils/browser.mjs +22 -0
- package/scripts/utils/canonical_home.mjs +20 -0
- package/scripts/utils/{cli_registry.mjs → cli/cli_registry.mjs} +71 -0
- package/scripts/utils/{wizard.mjs → cli/wizard.mjs} +1 -1
- package/scripts/utils/config.mjs +13 -1
- package/scripts/utils/dev_auth_key.mjs +169 -0
- package/scripts/utils/dev_daemon.mjs +104 -0
- package/scripts/utils/dev_expo_web.mjs +112 -0
- package/scripts/utils/dev_server.mjs +183 -0
- package/scripts/utils/env.mjs +94 -23
- package/scripts/utils/env_file.mjs +36 -0
- package/scripts/utils/expo.mjs +96 -0
- package/scripts/utils/handy_master_secret.mjs +94 -0
- package/scripts/utils/happy_server_infra.mjs +484 -0
- package/scripts/utils/localhost_host.mjs +17 -0
- package/scripts/utils/ownership.mjs +135 -0
- package/scripts/utils/paths.mjs +5 -2
- package/scripts/utils/pm.mjs +132 -22
- package/scripts/utils/ports.mjs +51 -13
- package/scripts/utils/proc.mjs +75 -7
- package/scripts/utils/runtime.mjs +1 -3
- package/scripts/utils/sandbox.mjs +14 -0
- package/scripts/utils/server.mjs +61 -0
- package/scripts/utils/server_port.mjs +9 -0
- package/scripts/utils/server_urls.mjs +54 -0
- package/scripts/utils/stack_context.mjs +23 -0
- package/scripts/utils/stack_runtime_state.mjs +104 -0
- package/scripts/utils/stack_startup.mjs +208 -0
- package/scripts/utils/stack_stop.mjs +255 -0
- package/scripts/utils/stacks.mjs +38 -0
- package/scripts/utils/validate.mjs +42 -1
- package/scripts/utils/watch.mjs +63 -0
- package/scripts/utils/worktrees.mjs +57 -1
- package/scripts/where.mjs +14 -7
- package/scripts/worktrees.mjs +135 -15
- /package/scripts/utils/{args.mjs → cli/args.mjs} +0 -0
- /package/scripts/utils/{cli.mjs → cli/cli.mjs} +0 -0
- /package/scripts/utils/{smoke_help.mjs → cli/smoke_help.mjs} +0 -0
|
@@ -8,13 +8,321 @@ is_git_repo() {
|
|
|
8
8
|
[[ -n "$dir" && -d "$dir" && ( -d "$dir/.git" || -f "$dir/.git" ) ]]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
git_cache_dir() {
|
|
12
|
+
local canonical="${HAPPY_STACKS_CANONICAL_HOME_DIR:-${HAPPY_LOCAL_CANONICAL_HOME_DIR:-$HOME/.happy-stacks}}"
|
|
13
|
+
local home="${HAPPY_STACKS_HOME_DIR:-${HAPPY_LOCAL_DIR:-$canonical}}"
|
|
14
|
+
local dir="${home}/cache/swiftbar/git"
|
|
15
|
+
mkdir -p "$dir" 2>/dev/null || true
|
|
16
|
+
echo "$dir"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
git_cache_ttl_sec() {
|
|
20
|
+
# Default: 6 hours.
|
|
21
|
+
local v="${HAPPY_STACKS_SWIFTBAR_GIT_TTL_SEC:-${HAPPY_LOCAL_SWIFTBAR_GIT_TTL_SEC:-21600}}"
|
|
22
|
+
[[ "$v" =~ ^[0-9]+$ ]] || v=21600
|
|
23
|
+
echo "$v"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
git_cache_refresh_on_stale() {
|
|
27
|
+
[[ "${HAPPY_STACKS_SWIFTBAR_GIT_REFRESH_ON_STALE:-${HAPPY_LOCAL_SWIFTBAR_GIT_REFRESH_ON_STALE:-0}}" == "1" ]]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
git_cache_auto_refresh_scope() {
|
|
31
|
+
# off | main | all
|
|
32
|
+
local s="${HAPPY_STACKS_SWIFTBAR_GIT_AUTO_REFRESH_SCOPE:-${HAPPY_LOCAL_SWIFTBAR_GIT_AUTO_REFRESH_SCOPE:-main}}"
|
|
33
|
+
s="$(echo "$s" | tr '[:upper:]' '[:lower:]')"
|
|
34
|
+
case "$s" in
|
|
35
|
+
off|none|0) echo "off" ;;
|
|
36
|
+
all) echo "all" ;;
|
|
37
|
+
*) echo "main" ;;
|
|
38
|
+
esac
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
git_cache_last_refresh_file() {
|
|
42
|
+
local scope="${1:-main}" # main|all|stack:<name>
|
|
43
|
+
local dir
|
|
44
|
+
dir="$(git_cache_dir)"
|
|
45
|
+
local key="last_refresh|${scope}"
|
|
46
|
+
echo "${dir}/$(swiftbar_cache_hash12 "$key").last"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
git_cache_background_refresh_lockdir() {
|
|
50
|
+
local scope="${1:-main}"
|
|
51
|
+
local dir
|
|
52
|
+
dir="$(git_cache_dir)"
|
|
53
|
+
local key="bg_refresh_lock|${scope}"
|
|
54
|
+
echo "${dir}/$(swiftbar_cache_hash12 "$key").lock"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
git_cache_touch_last_refresh() {
|
|
58
|
+
local scope="${1:-main}"
|
|
59
|
+
local f
|
|
60
|
+
f="$(git_cache_last_refresh_file "$scope")"
|
|
61
|
+
mkdir -p "$(dirname "$f")" 2>/dev/null || true
|
|
62
|
+
date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null >"$f" || true
|
|
63
|
+
touch "$f" 2>/dev/null || true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
git_cache_age_since_last_refresh_sec() {
|
|
67
|
+
local scope="${1:-main}"
|
|
68
|
+
local f
|
|
69
|
+
f="$(git_cache_last_refresh_file "$scope")"
|
|
70
|
+
[[ -f "$f" ]] || { echo ""; return; }
|
|
71
|
+
local mtime now
|
|
72
|
+
mtime="$(stat -f %m "$f" 2>/dev/null || echo 0)"
|
|
73
|
+
now="$(date +%s 2>/dev/null || echo 0)"
|
|
74
|
+
if [[ "$mtime" =~ ^[0-9]+$ && "$now" =~ ^[0-9]+$ && "$now" -ge "$mtime" ]]; then
|
|
75
|
+
echo $((now - mtime))
|
|
76
|
+
else
|
|
77
|
+
echo ""
|
|
78
|
+
fi
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
git_cache_maybe_refresh_async() {
|
|
82
|
+
# Non-blocking cache refresh.
|
|
83
|
+
# Usage: git_cache_maybe_refresh_async <scope> <refresh_cmd...>
|
|
84
|
+
local scope="$1"
|
|
85
|
+
shift
|
|
86
|
+
|
|
87
|
+
local ttl age
|
|
88
|
+
ttl="$(git_cache_ttl_sec)"
|
|
89
|
+
age="$(git_cache_age_since_last_refresh_sec "$scope")"
|
|
90
|
+
|
|
91
|
+
# If never refreshed, treat as stale and allow.
|
|
92
|
+
if [[ -n "$age" && "$age" =~ ^[0-9]+$ && "$age" -le "$ttl" ]]; then
|
|
93
|
+
return 0
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
local lockdir
|
|
97
|
+
lockdir="$(git_cache_background_refresh_lockdir "$scope")"
|
|
98
|
+
if [[ -d "$lockdir" ]]; then
|
|
99
|
+
# If lock is too old, break it (e.g. crashed refresh).
|
|
100
|
+
local lock_age
|
|
101
|
+
lock_age="$(git_cache_age_sec "$lockdir" 2>/dev/null || true)"
|
|
102
|
+
if [[ -n "$lock_age" && "$lock_age" =~ ^[0-9]+$ && "$lock_age" -gt 3600 ]]; then
|
|
103
|
+
rm -rf "$lockdir" 2>/dev/null || true
|
|
104
|
+
else
|
|
105
|
+
return 0
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
mkdir "$lockdir" 2>/dev/null || return 0
|
|
110
|
+
echo "$$" >"${lockdir}/pid" 2>/dev/null || true
|
|
111
|
+
date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null >"${lockdir}/started_at" || true
|
|
112
|
+
|
|
113
|
+
# Run in the background; on success, update last-refresh marker.
|
|
114
|
+
(
|
|
115
|
+
"$@" >/dev/null 2>&1 || true
|
|
116
|
+
git_cache_touch_last_refresh "$scope"
|
|
117
|
+
rm -rf "$lockdir" >/dev/null 2>&1 || true
|
|
118
|
+
) >/dev/null 2>&1 &
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
git_cache_mode() {
|
|
122
|
+
# cached (default) | live
|
|
123
|
+
local m="${HAPPY_STACKS_SWIFTBAR_GIT_MODE:-${HAPPY_LOCAL_SWIFTBAR_GIT_MODE:-cached}}"
|
|
124
|
+
m="$(echo "$m" | tr '[:upper:]' '[:lower:]')"
|
|
125
|
+
[[ "$m" == "live" ]] && echo "live" || echo "cached"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
git_cache_key() {
|
|
129
|
+
# Include context+stack because stacks can point components at different worktrees/dirs.
|
|
130
|
+
local context="$1"
|
|
131
|
+
local stack="$2"
|
|
132
|
+
local component="$3"
|
|
133
|
+
local active_dir="$4"
|
|
134
|
+
echo "ctx=${context}|stack=${stack}|comp=${component}|dir=${active_dir}"
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
git_cache_paths() {
|
|
138
|
+
# Usage: git_cache_paths <key>
|
|
139
|
+
# Output: meta<TAB>info<TAB>worktrees
|
|
140
|
+
local key="$1"
|
|
141
|
+
local dir
|
|
142
|
+
dir="$(git_cache_dir)"
|
|
143
|
+
local h
|
|
144
|
+
h="$(swiftbar_hash "$key")"
|
|
145
|
+
echo -e "${dir}/${h}.meta\t${dir}/${h}.info.tsv\t${dir}/${h}.worktrees.tsv"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
git_cache_age_sec() {
|
|
149
|
+
local meta="$1"
|
|
150
|
+
[[ -f "$meta" ]] || { echo ""; return; }
|
|
151
|
+
local mtime now
|
|
152
|
+
mtime="$(stat -f %m "$meta" 2>/dev/null || echo 0)"
|
|
153
|
+
now="$(date +%s 2>/dev/null || echo 0)"
|
|
154
|
+
if [[ "$mtime" =~ ^[0-9]+$ && "$now" =~ ^[0-9]+$ && "$now" -ge "$mtime" ]]; then
|
|
155
|
+
echo $((now - mtime))
|
|
156
|
+
else
|
|
157
|
+
echo ""
|
|
158
|
+
fi
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
git_cache_is_fresh() {
|
|
162
|
+
local meta="$1"
|
|
163
|
+
local ttl
|
|
164
|
+
ttl="$(git_cache_ttl_sec)"
|
|
165
|
+
local age
|
|
166
|
+
age="$(git_cache_age_sec "$meta")"
|
|
167
|
+
[[ -n "$age" && "$age" =~ ^[0-9]+$ && "$age" -le "$ttl" ]]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
git_cache_write_meta() {
|
|
171
|
+
local meta="$1"
|
|
172
|
+
local key="$2"
|
|
173
|
+
mkdir -p "$(dirname "$meta")" 2>/dev/null || true
|
|
174
|
+
{
|
|
175
|
+
echo "key=$key"
|
|
176
|
+
echo "updated_at=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || date)"
|
|
177
|
+
} >"$meta" 2>/dev/null || true
|
|
178
|
+
# touch to update mtime (age calculation uses mtime).
|
|
179
|
+
touch "$meta" 2>/dev/null || true
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
git_cache_refresh_one() {
|
|
183
|
+
# Computes and writes cached snapshot for one component context.
|
|
184
|
+
# Usage: git_cache_refresh_one <context> <stack> <component> <active_dir>
|
|
185
|
+
local context="$1"
|
|
186
|
+
local stack="$2"
|
|
187
|
+
local component="$3"
|
|
188
|
+
local active_dir="$4"
|
|
189
|
+
|
|
190
|
+
local key
|
|
191
|
+
key="$(git_cache_key "$context" "$stack" "$component" "$active_dir")"
|
|
192
|
+
local meta info wts
|
|
193
|
+
IFS=$'\t' read -r meta info wts <<<"$(git_cache_paths "$key")"
|
|
194
|
+
|
|
195
|
+
# Missing/non-repo: still write meta so we don't thrash.
|
|
196
|
+
if ! is_git_repo "$active_dir"; then
|
|
197
|
+
echo -e "missing\t${active_dir}\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-" >"$info" 2>/dev/null || true
|
|
198
|
+
: >"$wts" 2>/dev/null || true
|
|
199
|
+
git_cache_write_meta "$meta" "$key"
|
|
200
|
+
return 0
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# Collect snapshot.
|
|
204
|
+
local branch head upstream dirty ab ahead behind
|
|
205
|
+
branch="$(git_head_branch "$active_dir")"
|
|
206
|
+
head="$(git_head_short "$active_dir")"
|
|
207
|
+
upstream="$(git_upstream_short "$active_dir")"
|
|
208
|
+
dirty="$(git_dirty_flag "$active_dir")"
|
|
209
|
+
ab="$(git_ahead_behind "$active_dir")"
|
|
210
|
+
ahead=""
|
|
211
|
+
behind=""
|
|
212
|
+
if [[ -n "$ab" ]]; then
|
|
213
|
+
ahead="$(echo "$ab" | cut -d'|' -f1)"
|
|
214
|
+
behind="$(echo "$ab" | cut -d'|' -f2)"
|
|
215
|
+
fi
|
|
216
|
+
|
|
217
|
+
local main_branch main_upstream main_ab main_ahead main_behind
|
|
218
|
+
main_branch="$(git_main_branch_name "$active_dir")"
|
|
219
|
+
main_upstream=""
|
|
220
|
+
main_ahead=""
|
|
221
|
+
main_behind=""
|
|
222
|
+
if [[ -n "$main_branch" ]]; then
|
|
223
|
+
main_upstream="$(git_branch_upstream_short "$active_dir" "$main_branch")"
|
|
224
|
+
main_ab="$(git_branch_ahead_behind "$active_dir" "$main_branch")"
|
|
225
|
+
if [[ -n "$main_ab" ]]; then
|
|
226
|
+
main_ahead="$(echo "$main_ab" | cut -d'|' -f1)"
|
|
227
|
+
main_behind="$(echo "$main_ab" | cut -d'|' -f2)"
|
|
228
|
+
fi
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
local oref uref oab o_ahead o_behind uab u_ahead u_behind
|
|
232
|
+
oref="$(git_remote_main_ref "$active_dir" "origin")"
|
|
233
|
+
uref="$(git_remote_main_ref "$active_dir" "upstream")"
|
|
234
|
+
o_ahead=""; o_behind=""; u_ahead=""; u_behind=""
|
|
235
|
+
if [[ -n "$main_branch" && -n "$oref" ]]; then
|
|
236
|
+
oab="$(git_ahead_behind_refs "$active_dir" "$oref" "$main_branch")"
|
|
237
|
+
if [[ -n "$oab" ]]; then
|
|
238
|
+
o_ahead="$(echo "$oab" | cut -d'|' -f1)"
|
|
239
|
+
o_behind="$(echo "$oab" | cut -d'|' -f2)"
|
|
240
|
+
fi
|
|
241
|
+
fi
|
|
242
|
+
if [[ -n "$main_branch" && -n "$uref" ]]; then
|
|
243
|
+
uab="$(git_ahead_behind_refs "$active_dir" "$uref" "$main_branch")"
|
|
244
|
+
if [[ -n "$uab" ]]; then
|
|
245
|
+
u_ahead="$(echo "$uab" | cut -d'|' -f1)"
|
|
246
|
+
u_behind="$(echo "$uab" | cut -d'|' -f2)"
|
|
247
|
+
fi
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
local wt_count
|
|
251
|
+
wt_count="$(git_worktree_count "$active_dir")"
|
|
252
|
+
git_worktrees_tsv "$active_dir" >"$wts" 2>/dev/null || true
|
|
253
|
+
|
|
254
|
+
# status active_dir branch head upstream dirty ahead behind main_branch main_upstream main_ahead main_behind oref o_ahead o_behind uref u_ahead u_behind wt_count
|
|
255
|
+
echo -e "ok\t${active_dir}\t${branch}\t${head}\t${upstream}\t${dirty}\t${ahead}\t${behind}\t${main_branch}\t${main_upstream}\t${main_ahead}\t${main_behind}\t${oref}\t${o_ahead}\t${o_behind}\t${uref}\t${u_ahead}\t${u_behind}\t${wt_count}" >"$info" 2>/dev/null || true
|
|
256
|
+
git_cache_write_meta "$meta" "$key"
|
|
257
|
+
return 0
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
git_cache_load_or_refresh() {
|
|
261
|
+
# Usage: git_cache_load_or_refresh <context> <stack> <component> <active_dir> <allow_refresh_on_miss:0|1>
|
|
262
|
+
# Output: meta<TAB>info<TAB>worktrees<TAB>stale(0|1)
|
|
263
|
+
local context="$1"
|
|
264
|
+
local stack="$2"
|
|
265
|
+
local component="$3"
|
|
266
|
+
local active_dir="$4"
|
|
267
|
+
local allow_refresh_on_miss="${5:-0}"
|
|
268
|
+
|
|
269
|
+
local key
|
|
270
|
+
key="$(git_cache_key "$context" "$stack" "$component" "$active_dir")"
|
|
271
|
+
local meta info wts
|
|
272
|
+
IFS=$'\t' read -r meta info wts <<<"$(git_cache_paths "$key")"
|
|
273
|
+
|
|
274
|
+
# If cache exists and is fresh, use it.
|
|
275
|
+
if [[ -f "$meta" && -f "$info" ]]; then
|
|
276
|
+
if git_cache_is_fresh "$meta"; then
|
|
277
|
+
echo -e "${meta}\t${info}\t${wts}\t0"
|
|
278
|
+
return 0
|
|
279
|
+
fi
|
|
280
|
+
# Stale: do not refresh synchronously during menu render. Background refresh is handled elsewhere.
|
|
281
|
+
echo -e "${meta}\t${info}\t${wts}\t1"
|
|
282
|
+
return 0
|
|
283
|
+
fi
|
|
284
|
+
|
|
285
|
+
# Missing: only refresh synchronously when allowed by caller.
|
|
286
|
+
if [[ "$allow_refresh_on_miss" == "1" ]]; then
|
|
287
|
+
git_cache_refresh_one "$context" "$stack" "$component" "$active_dir" >/dev/null 2>&1 || true
|
|
288
|
+
if [[ -f "$info" ]]; then
|
|
289
|
+
echo -e "${meta}\t${info}\t${wts}\t0"
|
|
290
|
+
return 0
|
|
291
|
+
fi
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# Still missing; report missing and stale=1 so callers can show "refresh" action.
|
|
295
|
+
echo -e "${meta}\t${info}\t${wts}\t1"
|
|
296
|
+
return 0
|
|
297
|
+
}
|
|
298
|
+
|
|
11
299
|
git_try() {
|
|
12
300
|
local dir="$1"
|
|
13
301
|
shift
|
|
14
302
|
if ! command -v git >/dev/null 2>&1; then
|
|
15
303
|
return 1
|
|
16
304
|
fi
|
|
17
|
-
|
|
305
|
+
local subcmd="${1:-}"
|
|
306
|
+
|
|
307
|
+
# Run-cache: many stacks render the same component git info; cache by repo path + args for this SwiftBar run.
|
|
308
|
+
local cache_key="git|${dir}|$*"
|
|
309
|
+
swiftbar_cache_get "$cache_key"
|
|
310
|
+
local cached_rc=$?
|
|
311
|
+
if [[ $cached_rc -ne 111 ]]; then
|
|
312
|
+
# Cache hit: swiftbar_cache_get already printed stdout. Preserve rc.
|
|
313
|
+
return $cached_rc
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
local t0 t1 rc out
|
|
317
|
+
t0="$(swiftbar_now_ms 2>/dev/null || echo 0)"
|
|
318
|
+
out="$(git -C "$dir" "$@" 2>/dev/null)"
|
|
319
|
+
rc=$?
|
|
320
|
+
t1="$(swiftbar_now_ms 2>/dev/null || echo 0)"
|
|
321
|
+
swiftbar_cache_set "$cache_key" "$rc" "$out"
|
|
322
|
+
# Keep label short; include subcommand for aggregation.
|
|
323
|
+
swiftbar_profile_log "time" "label=git" "subcmd=$subcmd" "ms=$((t1 - t0))" "rc=${rc}"
|
|
324
|
+
printf '%s\n' "$out"
|
|
325
|
+
return $rc
|
|
18
326
|
}
|
|
19
327
|
|
|
20
328
|
git_head_branch() {
|
|
@@ -10,8 +10,8 @@ get_menu_icon_b64() {
|
|
|
10
10
|
fi
|
|
11
11
|
|
|
12
12
|
# Default: prefer a menu-bar friendly PNG icon (repo-local).
|
|
13
|
-
if [[ -z "$source" ]] && [[ -f "$HAPPY_LOCAL_DIR/extras/swiftbar/logo-white.png" ]]; then
|
|
14
|
-
source="$HAPPY_LOCAL_DIR/extras/swiftbar/logo-white.png"
|
|
13
|
+
if [[ -z "$source" ]] && [[ -f "$HAPPY_LOCAL_DIR/extras/swiftbar/icons/logo-white.png" ]]; then
|
|
14
|
+
source="$HAPPY_LOCAL_DIR/extras/swiftbar/icons/logo-white.png"
|
|
15
15
|
fi
|
|
16
16
|
|
|
17
17
|
# Fallback: use Happy's favicon if present.
|