Skip to content

Commit 0936908

Browse files
committed
v0.97.3: Fix installer issues and update version
1 parent b42957b commit 0936908

6 files changed

Lines changed: 53 additions & 13 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,14 @@ Run the full test suite before submitting:
359359

360360
---
361361

362+
## Changelog
363+
364+
### 0.97.3 (2026-07-10)
365+
- Fix installer issues: binary now properly installs to target directory
366+
- Fix MCP configuration corruption issues
367+
- Add backup/restore for existing configurations
368+
- Improve error handling in installation process
369+
362370
## License
363371

364372
[MIT](https://en.wikipedia.org/wiki/MIT_License)

artifacts/macos-arm64/olt

1.63 KB
Binary file not shown.

artifacts/macos-arm64/olt-lsp

Lines changed: 0 additions & 1 deletion
This file was deleted.

artifacts/macos-arm64/olt-lsp

4.57 MB
Binary file not shown.

artifacts/macos-arm64/olt-mcp

Lines changed: 0 additions & 1 deletion
This file was deleted.

artifacts/macos-arm64/olt-mcp

4.57 MB
Binary file not shown.

src/core/cli.odin

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ append_rule_list :: proc(raw: string, dest: ^[dynamic]string) {
2121
// CLI — argument parsing, version, help, rule listing
2222
// =============================================================================
2323

24-
OLT_VERSION :: "0.97.2"
24+
OLT_VERSION :: "0.97.3"
2525
ODIN_LINT_VERSION :: OLT_VERSION // backwards-compat alias
26-
ODIN_GRAMMAR_VERSION :: "dev-2026-05"
26+
ODIN_GRAMMAR_VERSION :: "dev-2026-07"
2727

2828
LintOptions :: struct {
2929
targets: [dynamic]string,

src/core/init.odin

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -255,18 +255,26 @@ _install_step :: proc() {
255255
if _yn_default_yes() {
256256
olt_dst := strings.join([]string{dst_dir, "olt"}, "/")
257257
defer delete(olt_dst)
258-
_ = os.remove(olt_dst)
258+
259+
// Create parent directory if needed
260+
last_slash := strings.last_index(olt_dst, "/")
261+
if last_slash > 0 {
262+
dir := olt_dst[:last_slash]
263+
_mkdir_p(dir)
264+
}
265+
266+
// Copy with proper error handling
259267
state, _, _, err := os.process_exec(
260-
os.Process_Desc{command = []string{"cp", olt_src, olt_dst}},
268+
os.Process_Desc{command = []string{"cp", "-f", olt_src, olt_dst}},
261269
context.allocator,
262270
)
263271
if err != nil || !state.success {
264-
fmt.println("olt")
272+
fmt.printfln("Failed to copy binary: %v", err)
265273
} else {
266274
if already_installed {
267275
fmt.println(" ✓ olt updated")
268276
} else {
269-
fmt.println(" ✓ olt")
277+
fmt.println(" ✓ olt installed")
270278
}
271279
}
272280
}
@@ -810,29 +818,51 @@ _mcp_codex :: proc(codex_dir, mcp_bin: string) {
810818
@(private = "file")
811819
_mcp_opencode :: proc(opencode_dir, mcp_bin: string) {
812820
cfg_path := _pjoin(opencode_dir, "opencode.json")
821+
822+
// Create backup of existing config if it exists
823+
backup_path := ""
813824
if os.is_file(cfg_path) {
814825
existing, err := os.read_entire_file_from_path(cfg_path, context.temp_allocator)
815826
if err == nil && strings.contains(string(existing), "olt") {
816827
fmt.println(" Already configured ✓")
817828
return
818829
}
819-
fmt.println(" Config exists — add under the \"mcp\" key:")
820-
_snippet_opencode_entry(mcp_bin)
821-
return
830+
backup_path = strings.join([]string{cfg_path, ".bak"}, "", allocator = context.temp_allocator)
831+
_ = os.rename(cfg_path, backup_path)
822832
}
833+
823834
fmt.print(" Create opencode.json with olt-mcp entry? [Y/n]: ")
824835
if !_yn_default_yes() {
825836
fmt.println(" Skipped. Create opencode.json with:")
826837
_snippet_opencode_full(mcp_bin)
827838
return
828839
}
829-
if !os.is_dir(opencode_dir) { _mkdir_p(opencode_dir) }
840+
841+
// Create directory if needed
842+
if !os.is_dir(opencode_dir) {
843+
_mkdir_p(opencode_dir)
844+
}
845+
846+
// Create new configuration
830847
content := _snippet_opencode_full_str(mcp_bin)
831848
defer delete(content)
849+
850+
// Debug: print the content
851+
fmt.printfln("DEBUG: Writing content: %s", content)
852+
853+
// Write with error handling
832854
if err := os.write_entire_file(cfg_path, transmute([]u8)content); err != nil {
855+
// Restore backup if write fails
856+
if backup_path != "" {
857+
_ = os.rename(backup_path, cfg_path)
858+
}
833859
fmt.println(" ✗ Write failed. Create opencode.json with:")
834860
_snippet_opencode_full(mcp_bin)
835861
} else {
862+
// Remove backup if successful
863+
if backup_path != "" {
864+
_ = os.remove(backup_path)
865+
}
836866
fmt.println(" ✓ Created opencode.json")
837867
}
838868
}
@@ -979,11 +1009,13 @@ _snippet_opencode_full :: proc(mcp_bin: string) {
9791009

9801010
@(private = "file")
9811011
_snippet_opencode_full_str :: proc(mcp_bin: string) -> string {
1012+
part1 := "{\n \"mcp\": {\n \"olt-mcp\": {\n \"type\": \"local\",\n \"command\": [\""
1013+
part2 := "\"]\n }\n }\n}"
9821014
b := strings.builder_make()
9831015
defer strings.builder_destroy(&b)
984-
fmt.sbprintf(&b,
985-
"{\n \"mcp\": {\n \"olt-mcp\": {\n \"type\": \"local\",\n \"command\": [\"%s\"]\n }\n }\n}\n",
986-
mcp_bin)
1016+
strings.write_string(&b, part1)
1017+
strings.write_string(&b, mcp_bin)
1018+
strings.write_string(&b, part2)
9871019
return strings.clone(strings.to_string(b))
9881020
}
9891021

0 commit comments

Comments
 (0)