forked from anomalyco/opencode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopencode-local
More file actions
executable file
·225 lines (199 loc) · 6.96 KB
/
Copy pathopencode-local
File metadata and controls
executable file
·225 lines (199 loc) · 6.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#!/usr/bin/env bash
set -euo pipefail
# opencode-local
#
# Single implementation of the local update/build/run cycle:
# 1) Merge upstream + origin into the current branch (interactive on conflicts).
# 2) Install dependencies and build the standalone binary.
# 3) Launch the freshly built binary.
#
# Each stage can be skipped independently so wrappers (see local-opencode-safe.sh)
# can reuse stages 1-2 and take over the launch themselves.
usage() {
cat <<'EOF'
Usage:
./opencode-local [options] [-- opencode args]
Options:
--no-update Skip fetch/merge/stash; leave the working tree as-is.
--no-build Skip `bun install` and the binary build.
--no-run Update and build, but do not launch OpenCode.
--mouse Enable mouse support (OPENCODE_DISABLE_MOUSE=0).
--no-mouse Disable mouse support (OPENCODE_DISABLE_MOUSE=1, default).
--help Show this help.
Any other arguments are passed through to the OpenCode binary.
Defaults to `--continue` when no binary arguments are given.
EOF
}
root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$root"
mkdir -p logs/analysis
binary="./packages/opencode/dist/opencode-linux-x64/bin/opencode"
update=1
build=1
run=1
disable_mouse="${OPENCODE_DISABLE_MOUSE:-1}"
declare -a args=()
while (($#)); do
case "$1" in
--no-update)
update=0
shift
;;
--no-build)
build=0
shift
;;
--no-run)
run=0
shift
;;
--mouse)
disable_mouse=0
shift
;;
--no-mouse)
disable_mouse=1
shift
;;
--help|-h)
usage
exit 0
;;
--)
shift
args+=("$@")
break
;;
*)
args+=("$1")
shift
;;
esac
done
declare -a skip_worktree_files=()
stashed=0
if [ "$update" -eq 1 ]; then
# Warn about leftover pre-merge stashes from prior runs. A clean pop auto-drops
# the stash; survivors mean a prior pop conflicted or the script was interrupted.
leftover=$(git stash list | grep -c "opencode-local: pre-merge stash" || true)
if [ "$leftover" -gt 0 ]; then
echo "WARNING: $leftover leftover pre-merge stash(es) from prior runs:"
git stash list | grep "opencode-local: pre-merge stash"
echo "Inspect: git stash show -p stash@{N}"
echo "Drop: git stash drop stash@{N}"
fi
echo "Updating repository..."
branch="$(git rev-parse --abbrev-ref HEAD)"
if ! git remote get-url upstream >/dev/null 2>&1; then
git remote add upstream https://github.com/anomalyco/opencode.git
fi
# Discard auto-generated SDK files that cause false merge conflicts.
# These are regenerated by @hey-api/openapi-ts with different formatting
# (single quotes, semicolons) than the project prettier config, producing
# large diffs that are pure noise and block git merge.
sdk_gen="packages/sdk/js/src/v2/gen"
if [ -d "$sdk_gen" ] && ! git diff --quiet -- "$sdk_gen" 2>/dev/null; then
echo "Discarding auto-generated SDK diffs (formatting noise)..."
git checkout -- "$sdk_gen" 2>/dev/null || true
git checkout -- packages/sdk/js/openapi.json 2>/dev/null || true
fi
# Temporarily lift skip-worktree flags so git merge can update those files.
# git diff hides skip-worktree files, so the stash below won't catch them,
# causing merge to abort with "would be overwritten". We restore the files to
# HEAD, merge proceeds, then re-apply the flag afterward.
mapfile -t skip_worktree_files < <(git ls-files -v | awk '/^S / {print $2}')
if [ ${#skip_worktree_files[@]} -gt 0 ]; then
for f in "${skip_worktree_files[@]}"; do
git update-index --no-skip-worktree "$f"
git checkout -- "$f"
done
fi
# Stash any remaining uncommitted changes so the merge can proceed.
# They'll be popped back after the merge (before build).
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "Stashing uncommitted local changes..."
git stash push -m "opencode-local: pre-merge stash $(date +%Y%m%dT%H%M%S)"
stashed=1
fi
git fetch upstream
upstream_ref="upstream/${branch}"
if ! git show-ref --verify --quiet "refs/remotes/${upstream_ref}"; then
upstream_ref="upstream/dev"
fi
if ! git merge --no-edit "${upstream_ref}"; then
if git rev-parse -q --verify MERGE_HEAD >/dev/null; then
echo "Merge in progress with conflicts."
else
echo "git merge ${upstream_ref} failed. Resolve and re-run."
exit 1
fi
fi
git fetch origin
origin_ref="origin/${branch}"
if git show-ref --verify --quiet "refs/remotes/${origin_ref}"; then
if ! git merge --no-edit "${origin_ref}"; then
if git rev-parse -q --verify MERGE_HEAD >/dev/null; then
echo "Merge in progress with conflicts."
else
echo "git merge ${origin_ref} failed. Resolve and re-run."
exit 1
fi
fi
fi
# Bailing out here (Ctrl-C) skips the merge commit, the stash pop, the
# skip-worktree restore, and `bun install` — the usual cause of a dangling
# MERGE_HEAD plus a typecheck that fails on unresolved workspace modules.
conflicts=$(git diff --name-only --diff-filter=U || true)
if [ -n "$conflicts" ]; then
echo "Conflicts detected:"
echo "$conflicts"
while [ -n "$conflicts" ]; do
read -rp "Resolve conflicts, then press Enter to continue (Ctrl+C to abort)..." _
conflicts=$(git diff --name-only --diff-filter=U || true)
if [ -n "$conflicts" ]; then
echo "Still conflicted:"
echo "$conflicts"
fi
done
fi
# Commit the merge if one is in progress (conflict resolution loop exits with
# all files staged but MERGE_HEAD still set — without this commit the next run
# re-merges and re-generates the same conflicts).
if git rev-parse -q --verify MERGE_HEAD >/dev/null 2>&1; then
echo "Committing merge..."
git commit --no-edit
fi
# Restore stashed local changes if any
if [ "$stashed" -eq 1 ]; then
echo "Restoring stashed local changes..."
if ! git stash pop; then
echo "WARNING: stash pop had conflicts. Your changes are in 'git stash list'."
echo "Resolve manually after this run, or run: git stash pop"
fi
fi
# Re-apply skip-worktree flags that were lifted before the merge.
if [ ${#skip_worktree_files[@]} -gt 0 ]; then
for f in "${skip_worktree_files[@]}"; do
if git ls-files --error-unmatch "$f" >/dev/null 2>&1; then
git update-index --skip-worktree "$f"
fi
done
fi
fi
# `bun install` is tied to the build rather than the update: a merge that adds or
# bumps a workspace dependency (e.g. a vendored tarball) leaves node_modules stale,
# and the resulting unresolved module detonates into dozens of misleading
# "implicitly has an 'any' type" errors in files that are themselves fine.
if [ "$build" -eq 1 ]; then
echo "Installing dependencies..."
bun install
echo "Building opencode..."
bun run --cwd packages/opencode script/build.ts --single
fi
if [ "$run" -eq 0 ]; then
exit 0
fi
if [ ${#args[@]} -eq 0 ]; then
args=(--continue)
fi
OPENCODE_DISABLE_MOUSE="$disable_mouse" "$binary" "${args[@]}"