From 36c00c7dc4ef68c493ffcf3b24f4ebc5fc6dd4a0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 13:24:24 +0000 Subject: [PATCH 01/10] build: follow moonbit 0.10.13 and moonbitlang/async 0.22 Bump every third-party dependency to its latest release and adapt the code to the toolchain and async API changes that broke the build: - moonbitlang/async 0.19.4 -> 0.22.1, moonbitlang/x 0.4.40 -> 0.5.5, bobzhang/toml 0.1.7 -> 0.4.3, mizchi/x 0.2.0 -> 0.6.1, mizchi/zlib 0.4.8 -> 0.4.9, mizchi/simd 0.4.1 -> 0.6.1, mizchi/llm 0.2.2 -> 0.3.2 (the old moonbitlang/x and toml releases no longer compile on the current compiler). - @http keys headers by CaseInsensitiveString: convert bit's plain String header maps at the transport boundary (bit_io_native, bit serve). - @fs.read_dir now returns an ArrayView: materialise it in the three RepoFileSystem::readdir implementations. - moonbitlang/core/strconv is empty now; use @string.parse_int / parse_int64 and drop the dead imports. - async cancellation is no longer an error and cannot be caught, so the `err if @async.is_cancellation_error(err) => raise err` guards are dead code (the function is deprecated and always returns false). Remove them and keep only the is_being_cancelled() checks. - Pin CI to the 0.10.13 compiler and bump the component pins to match. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- .github/actions/setup-moonbit/action.yaml | 7 ++-- component/moon.mod.json | 6 ++-- modules/bit/cmd/bit/am.mbt | 3 -- modules/bit/cmd/bit/bisect.mbt | 9 ----- modules/bit/cmd/bit/checkout.mbt | 2 -- modules/bit/cmd/bit/cherry_pick.mbt | 1 - modules/bit/cmd/bit/clean.mbt | 2 -- modules/bit/cmd/bit/clone.mbt | 10 +++--- modules/bit/cmd/bit/commit.mbt | 2 -- modules/bit/cmd/bit/fetch.mbt | 4 +-- modules/bit/cmd/bit/for_each_ref.mbt | 2 -- modules/bit/cmd/bit/grep.mbt | 2 -- modules/bit/cmd/bit/helpers.mbt | 2 +- modules/bit/cmd/bit/hq.mbt | 6 ++-- modules/bit/cmd/bit/hub_import.mbt | 4 --- modules/bit/cmd/bit/index_pack.mbt | 7 ---- modules/bit/cmd/bit/ls_tree.mbt | 1 - modules/bit/cmd/bit/main.mbt | 4 +-- modules/bit/cmd/bit/maintenance.mbt | 4 +-- modules/bit/cmd/bit/merge.mbt | 6 ---- modules/bit/cmd/bit/multi_pack_index.mbt | 7 ---- modules/bit/cmd/bit/notes.mbt | 1 - modules/bit/cmd/bit/osfs.mbt | 2 +- modules/bit/cmd/bit/pack_objects.mbt | 4 --- modules/bit/cmd/bit/push.mbt | 3 -- modules/bit/cmd/bit/rebase.mbt | 2 +- modules/bit/cmd/bit/remote.mbt | 14 ++++---- modules/bit/cmd/bit/rev_list.mbt | 1 - modules/bit/cmd/bit/revert.mbt | 10 ------ modules/bit/cmd/bit/scalar.mbt | 10 +++--- modules/bit/cmd/bit/serve.mbt | 4 +-- modules/bit/cmd/bit/serve_http.mbt | 26 +++++++++++---- modules/bit/cmd/bit/shell.mbt | 3 -- modules/bit/cmd/bit/show_branches.mbt | 2 -- modules/bit/cmd/bit/status.mbt | 1 - modules/bit/cmd/bit/subdir_clone.mbt | 6 ++-- modules/bit/cmd/bit/submodule.mbt | 18 +++++----- modules/bit/cmd/bit/upload_pack.mbt | 1 - modules/bit/cmd/bit/workspace.mbt | 4 --- modules/bit/cmd/git-bit/hub_import.mbt | 4 --- modules/bit/cmd/git-bit/osfs.mbt | 2 +- modules/bit/moon.mod | 14 ++++---- modules/bit_archive/src/moon.pkg | 1 - modules/bit_fast_import/src/moon.pkg | 1 - modules/bit_fingerprint/moon.mod | 2 +- modules/bit_hash/moon.mod | 2 +- modules/bit_io_native/moon.mod | 4 +-- .../bit_io_native/src/http_client_native.mbt | 33 ++++++++++++------- modules/bit_lib/moon.mod | 6 ++-- modules/bit_lib/src/moon.pkg | 1 - modules/bit_lib/src/native/worktree_modes.mbt | 1 - modules/bit_lib/src/object_db.mbt | 2 +- modules/bit_lib/src/reflog.mbt | 2 +- modules/bit_lib/src/upload_pack.mbt | 4 +-- modules/bit_object/moon.mod | 2 +- modules/bit_objstore/moon.mod | 2 +- modules/bit_osfs/moon.mod | 2 +- modules/bit_osfs/src/osfs.mbt | 2 +- modules/bit_pack/moon.mod | 6 ++-- modules/bit_pack_ops/moon.mod | 2 +- modules/bit_protocol/moon.mod | 2 +- modules/bit_runtime/moon.mod | 2 +- modules/bit_vfs/moon.mod | 6 ++-- modules/bit_worktree/moon.mod | 2 +- modules/bitx_bitconfig/moon.mod | 4 +-- modules/bitx_doc/moon.mod | 2 +- modules/bitx_hub/moon.mod | 6 ++-- modules/bitx_hub/src/native/sync_native.mbt | 4 +-- modules/bitx_kv/moon.mod | 6 ++-- modules/bitx_rebase_ai/moon.mod | 6 ++-- modules/bitx_subdir/moon.mod | 2 +- modules/bitx_wal/moon.mod | 2 +- modules/bitx_workspace/moon.mod | 4 +-- modules/bitx_workspace/src/workspace.mbt | 6 ++-- 74 files changed, 143 insertions(+), 209 deletions(-) diff --git a/.github/actions/setup-moonbit/action.yaml b/.github/actions/setup-moonbit/action.yaml index 9c26e7d5..851b3eca 100644 --- a/.github/actions/setup-moonbit/action.yaml +++ b/.github/actions/setup-moonbit/action.yaml @@ -5,9 +5,10 @@ inputs: version: description: MoonBit toolchain version required: false - # v0.10.7 ICEs while compiling moonbitlang/x@0.4.43. Keep CI on the - # last verified compiler until an upstream release fixes that regression. - default: "0.10.6+80dc50f24" + # Keep this on the toolchain the workspace is verified against: the + # dependency pins in modules/*/moon.mod (moonbitlang/async 0.22, + # moonbitlang/x 0.5, bobzhang/toml 0.4) need the 2026-09 compiler. + default: "0.10.13+cbb11c36f" runs: using: composite diff --git a/component/moon.mod.json b/component/moon.mod.json index 31c214e8..298aff32 100644 --- a/component/moon.mod.json +++ b/component/moon.mod.json @@ -5,9 +5,9 @@ "mizchi/bit": { "path": ".." }, - "mizchi/zlib": "0.3.0", - "moonbitlang/x": "0.4.40", - "mizchi/x": "0.1.4" + "mizchi/zlib": "0.4.9", + "moonbitlang/x": "0.5.5", + "mizchi/x": "0.6.1" }, "license": "Apache-2.0", "description": "WASM Component for bit-vcs git operations" diff --git a/modules/bit/cmd/bit/am.mbt b/modules/bit/cmd/bit/am.mbt index b0de527e..45f175f3 100644 --- a/modules/bit/cmd/bit/am.mbt +++ b/modules/bit/cmd/bit/am.mbt @@ -72,7 +72,6 @@ async fn handle_am(args : Array[String]) -> Unit raise Error { if fs.is_file(next_file) { let next = fs.read_file(next_file) |> decode_bytes |> trim_string let n = @string.parse_int(next) catch { - err if @async.is_cancellation_error(err) => raise err _ => 1 } fs.write_string(next_file, (n + 1).to_string()) @@ -278,11 +277,9 @@ async fn apply_remaining_patches( let last_str = fs.read_file(am_dir + "/last") |> decode_bytes |> trim_string let next_str = fs.read_file(am_dir + "/next") |> decode_bytes |> trim_string let last = @string.parse_int(last_str) catch { - err if @async.is_cancellation_error(err) => raise err _ => 0 } let mut next = @string.parse_int(next_str) catch { - err if @async.is_cancellation_error(err) => raise err _ => 1 } while next <= last { diff --git a/modules/bit/cmd/bit/bisect.mbt b/modules/bit/cmd/bit/bisect.mbt index 75ad989a..b464ad99 100644 --- a/modules/bit/cmd/bit/bisect.mbt +++ b/modules/bit/cmd/bit/bisect.mbt @@ -152,7 +152,6 @@ async fn bisect_mark( } let log_entry = "# \{mark_type}: [\{commit_hex}] \{commit_msg}\ngit bisect \{mark_type} \{commit_hex}\n" let existing_log = decode_bytes(rfs.read_file(bisect_log_path)) catch { - err if @async.is_cancellation_error(err) => raise err _ => "" } wfs.write_string(bisect_log_path, existing_log + log_entry) @@ -185,7 +184,6 @@ async fn bisect_skip( wfs.write_string(bisect_refs_dir + "/skip-" + commit_hex, commit_hex + "\n") let log_entry = "git bisect skip \{commit_hex}\n" let existing_log = decode_bytes(rfs.read_file(bisect_log_path)) catch { - err if @async.is_cancellation_error(err) => raise err _ => "" } wfs.write_string(bisect_log_path, existing_log + log_entry) @@ -210,7 +208,6 @@ fn bisect_compute_next( let good_commits : Array[@bitcore.ObjectId] = [] let skip_commits : Array[@bitcore.ObjectId] = [] let bisect_entries = (rfs : &@bitcore.RepoFileSystem).readdir(bisect_refs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } for entry in bisect_entries { @@ -392,7 +389,6 @@ async fn bisect_verify_good( let bisect_refs_dir = git_dir + "/refs/bisect" // Find a good commit let bisect_entries = (rfs : &@bitcore.RepoFileSystem).readdir(bisect_refs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } let mut good_hex : String? = None @@ -516,7 +512,6 @@ async fn bisect_visualize( // Collect good commits for --not let good_hexes : Array[String] = [] let bisect_entries = (rfs : &@bitcore.RepoFileSystem).readdir(bisect_refs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } for entry in bisect_entries { @@ -617,22 +612,18 @@ async fn bisect_reset( ] for path in cleanup_files { wfs.remove_file(path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } let entries = (rfs : &@bitcore.RepoFileSystem).readdir(bisect_refs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } for entry in entries { wfs.remove_file(bisect_refs_dir + "/" + entry) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } wfs.remove_file(bisect_refs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } eprint_line("Bisect reset") diff --git a/modules/bit/cmd/bit/checkout.mbt b/modules/bit/cmd/bit/checkout.mbt index dc4d2cb9..3eb6896b 100644 --- a/modules/bit/cmd/bit/checkout.mbt +++ b/modules/bit/cmd/bit/checkout.mbt @@ -284,7 +284,6 @@ fn checkout_cleanup_merge_state_files( let files = ["MERGE_HEAD", "MERGE_MSG", "MERGE_MODE", "SQUASH_MSG"] for file in files { fs.remove_file(git_dir + "/" + file) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } @@ -677,7 +676,6 @@ async fn checkout_with_promisor_retry( @bitlib.sparse_checkout_reapply(fs, fs, root) } @bitlibnative.apply_worktree_modes_from_commit(fs, fs, root, git_dir, id) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } return id diff --git a/modules/bit/cmd/bit/cherry_pick.mbt b/modules/bit/cmd/bit/cherry_pick.mbt index 0f90e416..d96db924 100644 --- a/modules/bit/cmd/bit/cherry_pick.mbt +++ b/modules/bit/cmd/bit/cherry_pick.mbt @@ -307,7 +307,6 @@ async fn handle_subdir_cherry_pick( let commit_info = @bitcore.parse_commit(co.data) catch { err => raise err } let parent_tree = if commit_info.parents.length() > 0 { get_subdir_tree_from_commit(db, fs, commit_info.parents[0], subdir_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => None } } else { diff --git a/modules/bit/cmd/bit/clean.mbt b/modules/bit/cmd/bit/clean.mbt index c138e7d0..e8dc33ac 100644 --- a/modules/bit/cmd/bit/clean.mbt +++ b/modules/bit/cmd/bit/clean.mbt @@ -93,13 +93,11 @@ async fn handle_clean(args : Array[String]) -> Unit raise Error { if fs.is_dir(abs_dir) { let rfs : &@bitcore.RepoFileSystem = fs let entries = rfs.readdir(abs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => continue } if entries.length() == 0 { let wfs : &@bitcore.FileSystem = fs wfs.remove_dir(abs_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } if !quiet { diff --git a/modules/bit/cmd/bit/clone.mbt b/modules/bit/cmd/bit/clone.mbt index a12609f5..bd9dc4b0 100644 --- a/modules/bit/cmd/bit/clone.mbt +++ b/modules/bit/cmd/bit/clone.mbt @@ -87,7 +87,7 @@ async fn handle_clone(args : Array[String]) -> Unit raise Error { let depth_str = args[i + 1] depth = @string.parse_int(depth_str) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 @@ -100,7 +100,7 @@ async fn handle_clone(args : Array[String]) -> Unit raise Error { let depth_str = String::unsafe_substring(arg, start=8, end=arg.length()) depth = @string.parse_int(depth_str) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 @@ -785,8 +785,7 @@ async fn handle_clone(args : Array[String]) -> Unit raise Error { Some(name) => { fs.mkdir_p(clone_git_dir + "/refs/heads") catch { err => { - if @async.is_being_cancelled() || - @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -797,8 +796,7 @@ async fn handle_clone(args : Array[String]) -> Unit raise Error { commit_id.to_hex() + "\n", ) catch { err => { - if @async.is_being_cancelled() || - @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () diff --git a/modules/bit/cmd/bit/commit.mbt b/modules/bit/cmd/bit/commit.mbt index b7254b20..2605022b 100644 --- a/modules/bit/cmd/bit/commit.mbt +++ b/modules/bit/cmd/bit/commit.mbt @@ -1148,7 +1148,6 @@ fn cleanup_merge_state_files( let files = ["MERGE_HEAD", "MERGE_MSG", "MERGE_MODE", "SQUASH_MSG"] for file in files { fs.remove_file(git_dir + "/" + file) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } @@ -1504,7 +1503,6 @@ fn commit_restore_index_backup(fs : OsFs, git_dir : String) -> Unit raise Error let data = (fs : &@bitcore.RepoFileSystem).read_file(backup_path) (fs : &@bitcore.FileSystem).write_file(index_path, data) (fs : &@bitcore.FileSystem).remove_file(backup_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } diff --git a/modules/bit/cmd/bit/fetch.mbt b/modules/bit/cmd/bit/fetch.mbt index 95970af8..89980a1b 100644 --- a/modules/bit/cmd/bit/fetch.mbt +++ b/modules/bit/cmd/bit/fetch.mbt @@ -192,7 +192,7 @@ async fn handle_fetch(args : Array[String]) -> Unit raise Error { if arg == "--depth" && i + 1 < args.length() { depth = @string.parse_int(args[i + 1]) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 @@ -205,7 +205,7 @@ async fn handle_fetch(args : Array[String]) -> Unit raise Error { let depth_str = String::unsafe_substring(arg, start=8, end=arg.length()) depth = @string.parse_int(depth_str) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 diff --git a/modules/bit/cmd/bit/for_each_ref.mbt b/modules/bit/cmd/bit/for_each_ref.mbt index 55fdbc04..3c3c79c4 100644 --- a/modules/bit/cmd/bit/for_each_ref.mbt +++ b/modules/bit/cmd/bit/for_each_ref.mbt @@ -49,7 +49,6 @@ async fn handle_for_each_ref(args : Array[String]) -> Unit raise Error { let val = String::unsafe_substring(arg, start=8, end=arg.length()) count = Some( @string.parse_int(val) catch { - err if @async.is_cancellation_error(err) => raise err _ => 0 }, ) @@ -163,7 +162,6 @@ async fn handle_for_each_ref(args : Array[String]) -> Unit raise Error { i += 1 count = Some( @string.parse_int(args[i]) catch { - err if @async.is_cancellation_error(err) => raise err _ => 0 }, ) diff --git a/modules/bit/cmd/bit/grep.mbt b/modules/bit/cmd/bit/grep.mbt index 61e6cf9c..7ddad45d 100644 --- a/modules/bit/cmd/bit/grep.mbt +++ b/modules/bit/cmd/bit/grep.mbt @@ -356,7 +356,6 @@ async fn handle_grep(args : Array[String]) -> Unit raise Error { expr_tokens, use_expr, ) catch { - err if @async.is_cancellation_error(err) => raise err err => raise err } i += 2 @@ -367,7 +366,6 @@ async fn handle_grep(args : Array[String]) -> Unit raise Error { grep_append_patterns_from_file( fs, root, file, patterns, expr_tokens, use_expr, ) catch { - err if @async.is_cancellation_error(err) => raise err err => raise err } i += 1 diff --git a/modules/bit/cmd/bit/helpers.mbt b/modules/bit/cmd/bit/helpers.mbt index 92cd5e96..460854dc 100644 --- a/modules/bit/cmd/bit/helpers.mbt +++ b/modules/bit/cmd/bit/helpers.mbt @@ -221,7 +221,7 @@ async fn run_git_command( let snapshot = enter_run_git_env(invocation.cwd, invocation.git_dir) let code = run_git_internal_command(invocation.cmd, invocation.rest) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { restore_run_git_env(snapshot) raise err } diff --git a/modules/bit/cmd/bit/hq.mbt b/modules/bit/cmd/bit/hq.mbt index 71d1a369..41f29b7f 100644 --- a/modules/bit/cmd/bit/hq.mbt +++ b/modules/bit/cmd/bit/hq.mbt @@ -116,7 +116,7 @@ async fn handle_hq_get(args : Array[String]) -> Unit raise Error { "--depth" if i + 1 < args.length() => { depth = @string.parse_int(args[i + 1]) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 @@ -128,7 +128,7 @@ async fn handle_hq_get(args : Array[String]) -> Unit raise Error { let depth_str = String::unsafe_substring(arg, start=8, end=arg.length()) depth = @string.parse_int(depth_str) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } 0 @@ -203,7 +203,7 @@ async fn handle_hq_get(args : Array[String]) -> Unit raise Error { let parent = get_parent_dir(local_path) fs.mkdir_p(parent) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () diff --git a/modules/bit/cmd/bit/hub_import.mbt b/modules/bit/cmd/bit/hub_import.mbt index c8ffb852..9e426156 100644 --- a/modules/bit/cmd/bit/hub_import.mbt +++ b/modules/bit/cmd/bit/hub_import.mbt @@ -142,13 +142,9 @@ async fn gh_collect_output( err => raise @bitcore.GitError::IoError("gh failed: \{err}") } let out = stdout.text() catch { - err if @async.is_cancellation_error(err) => - raise @bitcore.GitError::IoError(err.to_string()) _ => "" } let err_text = stderr.text() catch { - err if @async.is_cancellation_error(err) => - raise @bitcore.GitError::IoError(err.to_string()) _ => "" } if code != 0 { diff --git a/modules/bit/cmd/bit/index_pack.mbt b/modules/bit/cmd/bit/index_pack.mbt index 17e907d2..5713aacb 100644 --- a/modules/bit/cmd/bit/index_pack.mbt +++ b/modules/bit/cmd/bit/index_pack.mbt @@ -791,7 +791,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { } } let pack = @fs.read_file_to_bytes(pack_path) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "fatal: " + @debug.render(Repr(err)) + "\n", @@ -801,7 +800,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { } } let max_depth = @pack.max_delta_chain_length(pack) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "fatal: " + @debug.render(Repr(err)) + "\n", @@ -825,7 +823,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { } } let pack = @fs.read_file_to_bytes(pack_path) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "fatal: " + @debug.render(Repr(err)) + "\n", @@ -841,7 +838,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { pack_path + ".idx" } let idx = @fs.read_file_to_bytes(idx_path) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "fatal: " + @debug.render(Repr(err)) + "\n", @@ -865,7 +861,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { pack_path + ".rev" } let rev = @fs.read_file_to_bytes(rev_path) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "error: could not read reverse index: " + @@ -937,7 +932,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { } let bases = if cfg.fix_thin { @bitlib.load_all_objects_from_fs(fs, git_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } } else { @@ -1091,7 +1085,6 @@ async fn handle_index_pack(args : Array[String]) -> Unit raise Error { } let pack_path = resolve_in_cwd(pack_path) let pack = @fs.read_file_to_bytes(pack_path) catch { - err if @async.is_cancellation_error(err) => raise err err => { @stdio.stderr.write( "fatal: " + @debug.render(Repr(err)) + "\n", diff --git a/modules/bit/cmd/bit/ls_tree.mbt b/modules/bit/cmd/bit/ls_tree.mbt index 26cf24d3..8e64f0f5 100644 --- a/modules/bit/cmd/bit/ls_tree.mbt +++ b/modules/bit/cmd/bit/ls_tree.mbt @@ -269,7 +269,6 @@ async fn print_tree_entries( // entry.id is the commit SHA in the submodule // Resolve it to a tree let sub_tree_id = resolve_to_tree(sub_db, fs, entry.id) catch { - err if @async.is_cancellation_error(err) => raise err _ => continue // Skip if can't resolve submodule tree } // Recursively print submodule tree entries diff --git a/modules/bit/cmd/bit/main.mbt b/modules/bit/cmd/bit/main.mbt index c36d84f2..5a64eee1 100644 --- a/modules/bit/cmd/bit/main.mbt +++ b/modules/bit/cmd/bit/main.mbt @@ -845,7 +845,7 @@ async fn run_main_for_args(args : Array[String]) -> Unit { ) dispatch_command(dispatch_cmd, dispatch_rest) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } exit_with_error("dispatch", err) @@ -1245,7 +1245,7 @@ async fn dispatch_command( } dispatch_known_command(normalized_cmd, rest) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } exit_with_error(command_error_name(normalized_cmd), err) diff --git a/modules/bit/cmd/bit/maintenance.mbt b/modules/bit/cmd/bit/maintenance.mbt index ed9b86bf..d7a6f3bd 100644 --- a/modules/bit/cmd/bit/maintenance.mbt +++ b/modules/bit/cmd/bit/maintenance.mbt @@ -151,7 +151,7 @@ fn get_config_value_simple( async fn stage_all_changes(fs : OsFs, root : String) -> Unit raise Error { let status = @bitlib.status(fs, root) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } return @@ -170,7 +170,7 @@ async fn stage_all_changes(fs : OsFs, root : String) -> Unit raise Error { if all_paths.length() > 0 { let _ = @bitlib.add_paths_async(fs, fs, root, all_paths) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () diff --git a/modules/bit/cmd/bit/merge.mbt b/modules/bit/cmd/bit/merge.mbt index a4d97030..425374b9 100644 --- a/modules/bit/cmd/bit/merge.mbt +++ b/modules/bit/cmd/bit/merge.mbt @@ -290,15 +290,12 @@ async fn handle_merge(args : Array[String]) -> Unit raise Error { |> trim_string ignore(@bitlib.reset(wfs, rfs, root, orig_hex, @bitlib.ResetMode::Hard)) wfs.remove_file(orig_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(merge_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(git_dir + "/MERGE_MSG") catch { - err if @async.is_cancellation_error(err) => raise err _ => () } if !quiet { @@ -367,15 +364,12 @@ async fn handle_merge(args : Array[String]) -> Unit raise Error { let short = String::unsafe_substring(commit_id.to_hex(), start=0, end=7) // Clean up merge state wfs.remove_file(merge_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(merge_msg_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(git_dir + "/ORIG_HEAD") catch { - err if @async.is_cancellation_error(err) => raise err _ => () } if !quiet { diff --git a/modules/bit/cmd/bit/multi_pack_index.mbt b/modules/bit/cmd/bit/multi_pack_index.mbt index b6c8807d..8b5cff49 100644 --- a/modules/bit/cmd/bit/multi_pack_index.mbt +++ b/modules/bit/cmd/bit/multi_pack_index.mbt @@ -38,7 +38,6 @@ async fn handle_multi_pack_index(args : Array[String]) -> Unit raise Error { "--no-progress" => progress = false "--batch-size" if i + 1 < args.length() => { batch_size = @string.parse_int(args[i + 1]) catch { - err if @async.is_cancellation_error(err) => raise err _ => 0 } i += 2 @@ -46,7 +45,6 @@ async fn handle_multi_pack_index(args : Array[String]) -> Unit raise Error { } _ if arg.has_prefix("--batch-size=") => batch_size = @string.parse_int(arg[13:].to_owned()) catch { - err if @async.is_cancellation_error(err) => raise err _ => 0 } "--preferred-pack" if i + 1 < args.length() => { @@ -758,15 +756,12 @@ async fn midx_expire( let idx_path = pack_dir + "/" + pack_stem + ".idx" let rev_path = pack_dir + "/" + pack_stem + ".rev" fs.remove_file(pack_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } fs.remove_file(idx_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } fs.remove_file(rev_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } expired += 1 @@ -876,7 +871,6 @@ async fn midx_repack( let objects_dir = parent_dir(pack_dir) let git_dir = parent_dir(objects_dir) let db = @bitlib.ObjectDb::load(fs, git_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => { if progress { eprint_line("Unable to load object database") @@ -1292,7 +1286,6 @@ async fn midx_write_bitmap( let object_type_by_midx_pos : Array[Int] = Array::make(object_count, -1) for pack_idx, pack_name in pack_files { let pack_data = fs.read_file(pack_dir + "/" + pack_name) catch { - err if @async.is_cancellation_error(err) => raise err _ => { eprint_line("could not load pack") @sys.exit(1) diff --git a/modules/bit/cmd/bit/notes.mbt b/modules/bit/cmd/bit/notes.mbt index 00742c3e..09129c6a 100644 --- a/modules/bit/cmd/bit/notes.mbt +++ b/modules/bit/cmd/bit/notes.mbt @@ -842,7 +842,6 @@ async fn notes_prune( let (hex, id) = pair let ref_id = @bitcore.ObjectId::from_hex(hex) let ref_obj = db.get(rfs, ref_id) catch { - err if @async.is_cancellation_error(err) => raise err _ => None } match ref_obj { diff --git a/modules/bit/cmd/bit/osfs.mbt b/modules/bit/cmd/bit/osfs.mbt index 3f3d5fca..6bd2f552 100644 --- a/modules/bit/cmd/bit/osfs.mbt +++ b/modules/bit/cmd/bit/osfs.mbt @@ -52,7 +52,7 @@ pub impl @bitcore.RepoFileSystem for OsFs with fn read_file(_self, path) { ///| pub impl @bitcore.RepoFileSystem for OsFs with fn readdir(_self, path) { - @fs.read_dir(path) catch { + @fs.read_dir(path).to_array() catch { err => raise io_error(err) } } diff --git a/modules/bit/cmd/bit/pack_objects.mbt b/modules/bit/cmd/bit/pack_objects.mbt index 2db6606b..9b19b665 100644 --- a/modules/bit/cmd/bit/pack_objects.mbt +++ b/modules/bit/cmd/bit/pack_objects.mbt @@ -2418,7 +2418,6 @@ async fn try_reuse_single_stdin_pack( None => return false } let pack = fs.read_file(pack_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => return false } if cfg.stdout { @@ -2427,7 +2426,6 @@ async fn try_reuse_single_stdin_pack( } let idx_path = pack_idx_path(pack_path) let idx = fs.read_file(idx_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => return false } let hash_hex = pack_hash_hex(pack, hash_size~) @@ -2672,7 +2670,6 @@ async fn handle_pack_objects(args : Array[String]) -> Unit raise Error { ) } else if cfg.all { let refs = @bitrepo.show_ref(fs, git_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => [] } // Sort refs: branch refs (refs/heads/) first, then others. @@ -2873,7 +2870,6 @@ async fn handle_pack_objects(args : Array[String]) -> Unit raise Error { @bitlib.collect_reachable_objects_from_commits( db, fs, include_commits, ) catch { - err if @async.is_cancellation_error(err) => raise err err => { report_collect_error(err) [] diff --git a/modules/bit/cmd/bit/push.mbt b/modules/bit/cmd/bit/push.mbt index bd8b00a5..cede8937 100644 --- a/modules/bit/cmd/bit/push.mbt +++ b/modules/bit/cmd/bit/push.mbt @@ -2162,7 +2162,6 @@ async fn handle_subdir_push( ) -> Unit raise Error { // Step 1: Get local HEAD commit let local_head_opt = @bitrepo.rev_parse(fs, git_dir, "HEAD") catch { - err if @async.is_cancellation_error(err) => raise err _ => raise @bitcore.GitError::InvalidObject("Cannot resolve HEAD") } guard local_head_opt is Some(local_head) else { @@ -2171,7 +2170,6 @@ async fn handle_subdir_push( print_line(" Local HEAD: \{local_head.to_hex()}") // Step 2: Get the initial commit (first commit in the subdir-clone) let initial_commit = find_initial_subdir_commit(fs, git_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => raise @bitcore.GitError::InvalidObject("Cannot find initial commit") } print_line(" Initial commit: \{initial_commit.to_hex()}") @@ -2188,7 +2186,6 @@ async fn handle_subdir_push( print_line(" Found \{local_commits.length()} local commits to transform") // Step 4: Get upstream base commit let upstream_base = @bitcore.ObjectId::from_hex(base_hex) catch { - err if @async.is_cancellation_error(err) => raise err _ => raise @bitcore.GitError::InvalidObject("Cannot parse base commit") } print_line(" Upstream base: \{upstream_base.to_hex()}") diff --git a/modules/bit/cmd/bit/rebase.mbt b/modules/bit/cmd/bit/rebase.mbt index f554ea01..26693ce2 100644 --- a/modules/bit/cmd/bit/rebase.mbt +++ b/modules/bit/cmd/bit/rebase.mbt @@ -2159,7 +2159,7 @@ async fn handle_subdir_rebase( let upstream_path = git_dir + "/refs/remotes/" + target_ref let upstream_bytes = fs.read_file(upstream_path) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } print_line("Error: cannot resolve ref: \{target_ref}") diff --git a/modules/bit/cmd/bit/remote.mbt b/modules/bit/cmd/bit/remote.mbt index ad8dd3fa..2c3a18c0 100644 --- a/modules/bit/cmd/bit/remote.mbt +++ b/modules/bit/cmd/bit/remote.mbt @@ -392,7 +392,7 @@ async fn handle_remote(args : Array[String]) -> Unit raise Error { if progress { emit_trace_region("progress", "Renaming remote references") catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -828,7 +828,7 @@ async fn remote_remove( let msg = @bitlib.format_remove_warning(warn_branches) @stdio.stderr.write(str_to_bytes(msg)) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -1071,7 +1071,7 @@ async fn remote_rename( }) fs.remove_file(legacy_remotes) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -1112,7 +1112,7 @@ async fn remote_rename( }) fs.remove_file(legacy_branches) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -1155,7 +1155,7 @@ async fn remote_rename( if has_conflict { eprint_line("error: renaming remote references failed") catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -1165,7 +1165,7 @@ async fn remote_rename( "error: The remote you are trying to rename has conflicting references", ) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -2835,7 +2835,7 @@ async fn fetch_local_repo( } let object_id = @bitcore.ObjectId::from_hex(spec.src) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } continue diff --git a/modules/bit/cmd/bit/rev_list.mbt b/modules/bit/cmd/bit/rev_list.mbt index 390da7c0..a72b30c4 100644 --- a/modules/bit/cmd/bit/rev_list.mbt +++ b/modules/bit/cmd/bit/rev_list.mbt @@ -1267,7 +1267,6 @@ fn rev_list_is_long_numeric_option(arg : String) -> Bool { ///| async fn rev_list_parse_int_or_die(value : String) -> Int raise Error { @string.parse_int(value) catch { - err if @async.is_cancellation_error(err) => raise err _ => { eprint_line("fatal: not an integer: " + value) @sys.exit(128) diff --git a/modules/bit/cmd/bit/revert.mbt b/modules/bit/cmd/bit/revert.mbt index 5730a47b..e2d8b828 100644 --- a/modules/bit/cmd/bit/revert.mbt +++ b/modules/bit/cmd/bit/revert.mbt @@ -52,17 +52,14 @@ async fn handle_revert(args : Array[String]) -> Unit raise Error { // Reset to ORIG_HEAD ignore(@bitlib.reset(wfs, rfs, root, orig_hex, @bitlib.ResetMode::Hard)) wfs.remove_file(orig_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } // Clean up state files wfs.remove_file(revert_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(merge_msg_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } print_line("Revert aborted.") @@ -76,11 +73,9 @@ async fn handle_revert(args : Array[String]) -> Unit raise Error { } // Clean up state files (skip current revert) wfs.remove_file(revert_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(merge_msg_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } // Reset index to HEAD @@ -112,15 +107,12 @@ async fn handle_revert(args : Array[String]) -> Unit raise Error { print_line("[\{short_id}] \{first_line}") // Clean up state files wfs.remove_file(revert_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(merge_msg_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } wfs.remove_file(orig_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } return @@ -227,7 +219,6 @@ async fn handle_revert(args : Array[String]) -> Unit raise Error { let abs_path = root + "/" + path // Check if current file matches commit version (clean revert) let current_content = rfs.read_file(abs_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => b"" } let current_id = @bitcore.hash_blob(current_content) @@ -284,7 +275,6 @@ async fn handle_revert(args : Array[String]) -> Unit raise Error { } // Clean up ORIG_HEAD on success wfs.remove_file(orig_head_path) catch { - err if @async.is_cancellation_error(err) => raise err _ => () } } diff --git a/modules/bit/cmd/bit/scalar.mbt b/modules/bit/cmd/bit/scalar.mbt index 5cb131c5..c8affa0f 100644 --- a/modules/bit/cmd/bit/scalar.mbt +++ b/modules/bit/cmd/bit/scalar.mbt @@ -598,7 +598,7 @@ async fn scalar_handle_delete( } else if fs.is_file(target) { fs.remove_file(target) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -682,7 +682,7 @@ async fn scalar_handle_clone( if parsed.src { fs.mkdir_p(enlistment) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -838,7 +838,7 @@ async fn handle_scalar(args : Array[String]) -> Unit raise Error { "register" => scalar_handle_register(fs, cwd, subargs) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } scalar_die(1, err.to_string()) @@ -850,7 +850,7 @@ async fn handle_scalar(args : Array[String]) -> Unit raise Error { "reconfigure" => scalar_handle_reconfigure(fs, cwd, subargs) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } scalar_die(1, err.to_string()) @@ -861,7 +861,7 @@ async fn handle_scalar(args : Array[String]) -> Unit raise Error { "diagnose" => scalar_handle_diagnose(fs, cwd, subargs) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } scalar_die(1, err.to_string()) diff --git a/modules/bit/cmd/bit/serve.mbt b/modules/bit/cmd/bit/serve.mbt index 1c7bf6f6..abc37087 100644 --- a/modules/bit/cmd/bit/serve.mbt +++ b/modules/bit/cmd/bit/serve.mbt @@ -1179,7 +1179,7 @@ async fn handle_hub_serve(args : Array[String]) -> Unit raise Error { session_token~, ) catch { err => { - if @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { break } eprint_line("Poll error: \{err}, retrying...") @@ -1232,7 +1232,7 @@ async fn handle_hub_serve(args : Array[String]) -> Unit raise Error { incoming_refs~, ) catch { err => { - if @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { break } eprint_line("Respond error: \{err}") diff --git a/modules/bit/cmd/bit/serve_http.mbt b/modules/bit/cmd/bit/serve_http.mbt index e50055f8..802a4a30 100644 --- a/modules/bit/cmd/bit/serve_http.mbt +++ b/modules/bit/cmd/bit/serve_http.mbt @@ -178,13 +178,21 @@ fn http_token_ok(header : String?, expected : String?) -> Bool { } ///| -fn http_header(headers : Map[String, String], name : String) -> String? { - for key, value in headers { - if key.to_lower() == name { - return Some(value) - } +fn http_header(headers : @http.Headers, name : String) -> String? { + // `@http` keys headers by `CaseInsensitiveString`, so the lookup itself + // is already case-insensitive. + headers.get(@http.CaseInsensitiveString(name)) +} + +///| +/// bit's replies carry plain `String` header names; `@http` wants +/// `CaseInsensitiveString` keys. +fn http_reply_headers(headers : Map[String, String]) -> @http.Headers { + let out : @http.Headers = Map([]) + for name, value in headers { + out[@http.CaseInsensitiveString(name)] = value } - None + out } ///| @@ -400,7 +408,11 @@ async fn http_serve_run(options : HttpServeOptions) -> Unit raise Error { http_text_reply(500, "Internal Server Error", "internal error\n") } } - conn.send_response(reply.status, reply.reason, extra_headers=reply.headers) + conn.send_response( + reply.status, + reply.reason, + extra_headers=http_reply_headers(reply.headers), + ) if reply.body.length() > 0 { conn.write(reply.body) } diff --git a/modules/bit/cmd/bit/shell.mbt b/modules/bit/cmd/bit/shell.mbt index 64e1555e..69599577 100644 --- a/modules/bit/cmd/bit/shell.mbt +++ b/modules/bit/cmd/bit/shell.mbt @@ -102,17 +102,14 @@ async fn shell_run_service_command(command_line : String) -> Unit raise Error { match service { "git-upload-pack" => handle_upload_pack([path]) catch { - err if @async.is_cancellation_error(err) => raise err err => exit_with_error("upload-pack", err) } "git-receive-pack" => handle_receive_pack([path]) catch { - err if @async.is_cancellation_error(err) => raise err err => exit_with_error("receive-pack", err) } "git-upload-archive" => handle_upload_archive([path]) catch { - err if @async.is_cancellation_error(err) => raise err err => exit_with_error("upload-archive", err) } _ => { diff --git a/modules/bit/cmd/bit/show_branches.mbt b/modules/bit/cmd/bit/show_branches.mbt index 32e6d52e..f7ca2208 100644 --- a/modules/bit/cmd/bit/show_branches.mbt +++ b/modules/bit/cmd/bit/show_branches.mbt @@ -16,7 +16,6 @@ async fn handle_show_branches(args : Array[String]) -> Unit raise Error { "-r" | "--remotes" => show_remotes = true "--more" if i + 1 < args.length() => { max_count = @string.parse_int(args[i + 1]) catch { - err if @async.is_cancellation_error(err) => raise err _ => 10 } i += 2 @@ -25,7 +24,6 @@ async fn handle_show_branches(args : Array[String]) -> Unit raise Error { _ if arg.has_prefix("--more=") => { let val = String::unsafe_substring(arg, start=7, end=arg.length()) max_count = @string.parse_int(val) catch { - err if @async.is_cancellation_error(err) => raise err _ => 10 } } diff --git a/modules/bit/cmd/bit/status.mbt b/modules/bit/cmd/bit/status.mbt index 1c4f7a6f..d02b6dd7 100644 --- a/modules/bit/cmd/bit/status.mbt +++ b/modules/bit/cmd/bit/status.mbt @@ -115,7 +115,6 @@ async fn handle_status(args : Array[String]) -> Unit raise Error { if porcelain || short { if show_branch { let head = @bitlib.read_head_ref(fs, git_dir) catch { - err if @async.is_cancellation_error(err) => raise err _ => return () } match head { diff --git a/modules/bit/cmd/bit/subdir_clone.mbt b/modules/bit/cmd/bit/subdir_clone.mbt index 751a980a..05e25d02 100644 --- a/modules/bit/cmd/bit/subdir_clone.mbt +++ b/modules/bit/cmd/bit/subdir_clone.mbt @@ -259,7 +259,7 @@ async fn subdir_clone( let head_path = git_dir + "/HEAD" fs.write_file(head_path, string_to_bytes("ref: refs/heads/main\n")) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -268,7 +268,7 @@ async fn subdir_clone( let ref_path = git_dir + "/refs/heads/main" fs.mkdir_p(git_dir + "/refs/heads") catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -276,7 +276,7 @@ async fn subdir_clone( } fs.write_file(ref_path, string_to_bytes(new_commit_id.to_hex() + "\n")) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () diff --git a/modules/bit/cmd/bit/submodule.mbt b/modules/bit/cmd/bit/submodule.mbt index 3074b6da..b0b6c87e 100644 --- a/modules/bit/cmd/bit/submodule.mbt +++ b/modules/bit/cmd/bit/submodule.mbt @@ -1040,7 +1040,7 @@ async fn handle_submodule_add( fs, fs, sub_path, active_sub_git_dir, target_id, ) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } eprint_line( @@ -2075,7 +2075,7 @@ async fn handle_submodule_status( let sub_git_dir = @bitlib.resolve_gitdir(rfs, sub_git) let head_id = @bitlib.resolve_head_commit(rfs, sub_git_dir) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } print_line( @@ -2258,7 +2258,7 @@ async fn handle_submodule_update( let _gitfile_content = decode_bytes( rfs.read_file(gitfile) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } Default::default() @@ -2490,7 +2490,7 @@ async fn handle_submodule_update( fs, fs, sub_path, sub_git_dir, target_id, ) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } eprint_line( @@ -2960,8 +2960,7 @@ async fn handle_submodule_deinit( Some(actual_sub_git_dir) if rfs.is_dir(actual_sub_git_dir) => { let status = @bitlib.status(rfs, sub_path) catch { err => { - if @async.is_being_cancelled() || - @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } @stdio.stderr.write( @@ -3012,7 +3011,7 @@ async fn handle_submodule_deinit( if rfs.is_dir(sub_path) { let entries = rfs.readdir(sub_path) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } continue @@ -3029,8 +3028,7 @@ async fn handle_submodule_deinit( } else { wfs.remove_file(full) catch { err => { - if @async.is_being_cancelled() || - @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } () @@ -3516,7 +3514,7 @@ async fn handle_submodule_foreach( let sub_git_dir = @bitlib.resolve_gitdir(rfs, sub_git) let head_id = @bitlib.resolve_head_commit(rfs, sub_git_dir) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } continue diff --git a/modules/bit/cmd/bit/upload_pack.mbt b/modules/bit/cmd/bit/upload_pack.mbt index f8a7896c..7c43735a 100644 --- a/modules/bit/cmd/bit/upload_pack.mbt +++ b/modules/bit/cmd/bit/upload_pack.mbt @@ -107,7 +107,6 @@ async fn handle_upload_pack(args : Array[String]) -> Unit raise Error { } } } catch { - err if @async.is_cancellation_error(err) => raise err err => upload_pack_fail(err, protocol_version, advertise) } } diff --git a/modules/bit/cmd/bit/workspace.mbt b/modules/bit/cmd/bit/workspace.mbt index 900dc19d..747206a0 100644 --- a/modules/bit/cmd/bit/workspace.mbt +++ b/modules/bit/cmd/bit/workspace.mbt @@ -63,10 +63,6 @@ async fn run_workspace_repo_command( let mut code = 0 let mut message = "" run_workspace_repo_command_inner(cmd, rest) catch { - err if @async.is_cancellation_error(err) => { - restore_run_git_env(snapshot) - raise err - } err => { code = 1 message = err.to_string() diff --git a/modules/bit/cmd/git-bit/hub_import.mbt b/modules/bit/cmd/git-bit/hub_import.mbt index 6f452b77..663882de 100644 --- a/modules/bit/cmd/git-bit/hub_import.mbt +++ b/modules/bit/cmd/git-bit/hub_import.mbt @@ -142,13 +142,9 @@ async fn gh_collect_output( err => raise @bitcore.GitError::IoError("gh failed: \{err}") } let out = stdout.text() catch { - err if @async.is_cancellation_error(err) => - raise @bitcore.GitError::IoError(err.to_string()) _ => "" } let err_text = stderr.text() catch { - err if @async.is_cancellation_error(err) => - raise @bitcore.GitError::IoError(err.to_string()) _ => "" } if code != 0 { diff --git a/modules/bit/cmd/git-bit/osfs.mbt b/modules/bit/cmd/git-bit/osfs.mbt index 3f3d5fca..6bd2f552 100644 --- a/modules/bit/cmd/git-bit/osfs.mbt +++ b/modules/bit/cmd/git-bit/osfs.mbt @@ -52,7 +52,7 @@ pub impl @bitcore.RepoFileSystem for OsFs with fn read_file(_self, path) { ///| pub impl @bitcore.RepoFileSystem for OsFs with fn readdir(_self, path) { - @fs.read_dir(path) catch { + @fs.read_dir(path).to_array() catch { err => raise io_error(err) } } diff --git a/modules/bit/moon.mod b/modules/bit/moon.mod index 1bb85ea5..e3d396e8 100644 --- a/modules/bit/moon.mod +++ b/modules/bit/moon.mod @@ -3,16 +3,16 @@ name = "mizchi/bit" version = "0.46.4" import { - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", - "mizchi/simd@0.4.1", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", + "mizchi/simd@0.6.1", "mizchi/tempfile@0.1.2", - "mizchi/llm@0.2.2", + "mizchi/llm@0.3.2", "mizchi/bitflow@0.4.1", - "mizchi/x@0.2.0", - "bobzhang/toml@0.1.7", + "mizchi/x@0.6.1", + "bobzhang/toml@0.4.3", "mizchi/libgit2@0.1.0", - "mizchi/zlib@0.4.8", + "mizchi/zlib@0.4.9", "mizchi/experimental_crypto@0.0.2", "mizchi/bitx_openpgp@0.46.4", "mizchi/bit_apply@0.46.4", diff --git a/modules/bit_archive/src/moon.pkg b/modules/bit_archive/src/moon.pkg index 82d7a527..3ee8913b 100644 --- a/modules/bit_archive/src/moon.pkg +++ b/modules/bit_archive/src/moon.pkg @@ -1,5 +1,4 @@ import { "moonbitlang/core/encoding/utf8", "moonbitlang/core/string", - "moonbitlang/core/strconv", } diff --git a/modules/bit_fast_import/src/moon.pkg b/modules/bit_fast_import/src/moon.pkg index fe8d4b4b..260e1e66 100644 --- a/modules/bit_fast_import/src/moon.pkg +++ b/modules/bit_fast_import/src/moon.pkg @@ -1,7 +1,6 @@ import { "moonbitlang/core/encoding/utf8", "moonbitlang/core/string", - "moonbitlang/core/strconv", } import { diff --git a/modules/bit_fingerprint/moon.mod b/modules/bit_fingerprint/moon.mod index 46789aa4..69cad8df 100644 --- a/modules/bit_fingerprint/moon.mod +++ b/modules/bit_fingerprint/moon.mod @@ -9,7 +9,7 @@ import { "mizchi/bit_osfs@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_utils@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_hash/moon.mod b/modules/bit_hash/moon.mod index 786e9544..ded38ac0 100644 --- a/modules/bit_hash/moon.mod +++ b/modules/bit_hash/moon.mod @@ -3,7 +3,7 @@ name = "mizchi/bit_hash" version = "0.46.4" import { - "mizchi/simd@0.4.1", + "mizchi/simd@0.6.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_io_native/moon.mod b/modules/bit_io_native/moon.mod index 083c81e3..4e165844 100644 --- a/modules/bit_io_native/moon.mod +++ b/modules/bit_io_native/moon.mod @@ -11,8 +11,8 @@ import { "mizchi/bit_protocol@0.46.4", "mizchi/bit_repo@0.46.4", "mizchi/bit_types@0.46.4", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } readme = "README.mbt.md" diff --git a/modules/bit_io_native/src/http_client_native.mbt b/modules/bit_io_native/src/http_client_native.mbt index fc5853d9..592f986e 100644 --- a/modules/bit_io_native/src/http_client_native.mbt +++ b/modules/bit_io_native/src/http_client_native.mbt @@ -168,8 +168,6 @@ async fn bit_credential_fill( return None } let text = stdout.text() catch { - err if @async.is_cancellation_error(err) => - raise @bit.GitError::IoError(err.to_string()) _ => "" } let mut user : String? = None @@ -259,8 +257,6 @@ async fn collect_response( let chunks : Array[Byte] = [] while true { let chunk = client.read_some() catch { - err if @async.is_cancellation_error(err) => - raise @bit.GitError::IoError(err.to_string()) err => if strict { raise @bit.GitError::IoError("HTTP response body truncated: \{err}") @@ -287,11 +283,22 @@ async fn collect_response( fn http_response_of(response : @http.Response) -> @bit.HttpResponse { let headers : Map[String, String] = Map([]) for name, value in response.headers { - headers[name] = value + headers[name.0] = value } @bit.HttpResponse::with_headers(response.code, headers) } +///| +/// `@http` keys request headers by `CaseInsensitiveString` (async 0.22+); +/// bit's transport-neutral interfaces keep plain `String` keys. +fn to_http_headers(headers : Map[String, String]) -> @http.Headers { + let out : @http.Headers = Map([]) + for name, value in headers { + out[@http.CaseInsensitiveString(name)] = value + } + out +} + ///| /// Split an absolute URL into the origin a `Client` connects to and the path /// a request line carries. @@ -317,7 +324,7 @@ pub async fn native_http_get( headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { let auth_headers = apply_auth_header(url, headers) - let (response, client) = @http.get_stream(url, headers=auth_headers) catch { + let (response, client) = @http.get_stream(url, headers=to_http_headers(auth_headers)) catch { e => raise @bit.GitError::IoError("HTTP GET failed: \{e}") } let data = drain_response(client) @@ -331,7 +338,7 @@ pub async fn native_http_post( headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { let auth_headers = apply_auth_header(url, headers) - let client = @http.post_stream(url, headers=auth_headers) catch { + let client = @http.post_stream(url, headers=to_http_headers(auth_headers)) catch { e => raise @bit.GitError::IoError("HTTP POST failed: \{e}") } client.write(body) catch { @@ -370,7 +377,7 @@ pub async fn native_http_put( headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { let auth_headers = apply_auth_header(url, headers) - let client = @http.put_stream(url, headers=auth_headers) catch { + let client = @http.put_stream(url, headers=to_http_headers(auth_headers)) catch { e => raise @bit.GitError::IoError("HTTP PUT failed: \{e}") } client.write(body) catch { @@ -399,7 +406,11 @@ pub async fn native_http_delete( e => raise @bit.GitError::IoError("HTTP DELETE connect failed: \{e}") } let response = try { - client.request(@http.RequestMethod::Delete, path, extra_headers=auth_headers) + client.request( + @http.RequestMethod::Delete, + path, + extra_headers=to_http_headers(auth_headers), + ) client.end_request() } catch { e => { @@ -442,7 +453,7 @@ pub async fn native_objstore_send( e => raise @bit.GitError::IoError("connect to \{origin} failed: \{e}") } let response = try { - client.request(request_method, path, extra_headers=headers) + client.request(request_method, path, extra_headers=to_http_headers(headers)) if body.length() > 0 { client.write(body) } @@ -456,7 +467,7 @@ pub async fn native_objstore_send( let data = drain_response_strict(client) let out_headers : Map[String, String] = Map([]) for name, value in response.headers { - out_headers[name] = value + out_headers[name.0] = value } { status: response.code, headers: out_headers, body: data } } diff --git a/modules/bit_lib/moon.mod b/modules/bit_lib/moon.mod index 03ef6ad0..1bbff7ed 100644 --- a/modules/bit_lib/moon.mod +++ b/modules/bit_lib/moon.mod @@ -21,9 +21,9 @@ import { "mizchi/bit_repo@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_utils@0.46.4", - "mizchi/zlib@0.4.8", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "mizchi/zlib@0.4.9", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_lib/src/moon.pkg b/modules/bit_lib/src/moon.pkg index 615dbd3d..6d6bae81 100644 --- a/modules/bit_lib/src/moon.pkg +++ b/modules/bit_lib/src/moon.pkg @@ -21,7 +21,6 @@ import { "moonbitlang/core/bench", "moonbitlang/core/encoding/utf8", "moonbitlang/core/string", - "moonbitlang/core/strconv", } import { diff --git a/modules/bit_lib/src/native/worktree_modes.mbt b/modules/bit_lib/src/native/worktree_modes.mbt index a552209c..a336677b 100644 --- a/modules/bit_lib/src/native/worktree_modes.mbt +++ b/modules/bit_lib/src/native/worktree_modes.mbt @@ -167,7 +167,6 @@ async fn apply_file_mode(path : String, mode : Int) -> Unit raise @bit.GitError ///| async fn remove_path_if_exists(path : String) -> Unit raise @bit.GitError { let exists = @afs.exists(path) catch { - err if @async.is_cancellation_error(err) => abort("cancelled") _ => false } if !exists { diff --git a/modules/bit_lib/src/object_db.mbt b/modules/bit_lib/src/object_db.mbt index 923f249d..8e257ec8 100644 --- a/modules/bit_lib/src/object_db.mbt +++ b/modules/bit_lib/src/object_db.mbt @@ -3,7 +3,7 @@ ///| #warnings("-deprecated") fn object_db_parse_int(value : StringView) -> Int raise { - @strconv.parse_int(value) + @string.parse_int(value) } ///| diff --git a/modules/bit_lib/src/reflog.mbt b/modules/bit_lib/src/reflog.mbt index fe1c9cec..e9a2bcb9 100644 --- a/modules/bit_lib/src/reflog.mbt +++ b/modules/bit_lib/src/reflog.mbt @@ -3,7 +3,7 @@ ///| #warnings("-deprecated") fn reflog_parse_int64(value : StringView) -> Int64 raise { - @strconv.parse_int64(value) + @string.parse_int64(value) } ///| diff --git a/modules/bit_lib/src/upload_pack.mbt b/modules/bit_lib/src/upload_pack.mbt index 90d9d7d0..01fd6b7f 100644 --- a/modules/bit_lib/src/upload_pack.mbt +++ b/modules/bit_lib/src/upload_pack.mbt @@ -3,13 +3,13 @@ ///| #warnings("-deprecated") fn upload_pack_parse_int(value : StringView) -> Int raise { - @strconv.parse_int(value) + @string.parse_int(value) } ///| #warnings("-deprecated") fn upload_pack_parse_int64(value : StringView) -> Int64 raise { - @strconv.parse_int64(value) + @string.parse_int64(value) } ///| diff --git a/modules/bit_object/moon.mod b/modules/bit_object/moon.mod index a7d124f3..a4e08310 100644 --- a/modules/bit_object/moon.mod +++ b/modules/bit_object/moon.mod @@ -4,7 +4,7 @@ version = "0.46.4" import { "mizchi/bit_hash@0.46.4", - "mizchi/zlib@0.4.8", + "mizchi/zlib@0.4.9", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_objstore/moon.mod b/modules/bit_objstore/moon.mod index 5cc72b7d..0b580e01 100644 --- a/modules/bit_objstore/moon.mod +++ b/modules/bit_objstore/moon.mod @@ -6,7 +6,7 @@ import { "mizchi/bit_hash@0.46.4", "mizchi/bit_object@0.46.4", "mizchi/bit_types@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_osfs/moon.mod b/modules/bit_osfs/moon.mod index 2e519e2c..89c2841c 100644 --- a/modules/bit_osfs/moon.mod +++ b/modules/bit_osfs/moon.mod @@ -7,7 +7,7 @@ import { "mizchi/bit_io@0.46.4", "mizchi/bit_object@0.46.4", "mizchi/bit_types@0.46.4", - "moonbitlang/x@0.4.40", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_osfs/src/osfs.mbt b/modules/bit_osfs/src/osfs.mbt index 5ee686f5..2a1aca8a 100644 --- a/modules/bit_osfs/src/osfs.mbt +++ b/modules/bit_osfs/src/osfs.mbt @@ -88,7 +88,7 @@ pub impl @bit.RepoFileSystem for OsFs with fn read_file(_self, path) { ///| pub impl @bit.RepoFileSystem for OsFs with fn readdir(_self, path) { - @fs.read_dir(path) catch { + @fs.read_dir(path).to_array() catch { err => raise io_error(err) } } diff --git a/modules/bit_pack/moon.mod b/modules/bit_pack/moon.mod index 81f98456..e5fbd57b 100644 --- a/modules/bit_pack/moon.mod +++ b/modules/bit_pack/moon.mod @@ -8,9 +8,9 @@ import { "mizchi/bit_repo@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/tempfile@0.1.2", - "mizchi/zlib@0.4.8", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "mizchi/zlib@0.4.9", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_pack_ops/moon.mod b/modules/bit_pack_ops/moon.mod index a8ba47ac..746e7cc6 100644 --- a/modules/bit_pack_ops/moon.mod +++ b/modules/bit_pack_ops/moon.mod @@ -9,7 +9,7 @@ import { "mizchi/bit_object@0.46.4", "mizchi/bit_pack@0.46.4", "mizchi/bit_types@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_protocol/moon.mod b/modules/bit_protocol/moon.mod index 5810160a..53d050c1 100644 --- a/modules/bit_protocol/moon.mod +++ b/modules/bit_protocol/moon.mod @@ -9,7 +9,7 @@ import { "mizchi/bit_repo@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_pack@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_runtime/moon.mod b/modules/bit_runtime/moon.mod index c54f58f5..57b9dec8 100644 --- a/modules/bit_runtime/moon.mod +++ b/modules/bit_runtime/moon.mod @@ -11,7 +11,7 @@ import { "mizchi/bit_repo_ops@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_utils@0.46.4", - "moonbitlang/x@0.4.40", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_vfs/moon.mod b/modules/bit_vfs/moon.mod index 459c9d27..4227fc69 100644 --- a/modules/bit_vfs/moon.mod +++ b/modules/bit_vfs/moon.mod @@ -10,9 +10,9 @@ import { "mizchi/bit_osfs@0.46.4", "mizchi/bit_repo@0.46.4", "mizchi/bit_types@0.46.4", - "mizchi/zlib@0.4.8", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "mizchi/zlib@0.4.9", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bit_worktree/moon.mod b/modules/bit_worktree/moon.mod index 9e9110d6..14b7f2b4 100644 --- a/modules/bit_worktree/moon.mod +++ b/modules/bit_worktree/moon.mod @@ -8,7 +8,7 @@ import { "mizchi/bit_lib@0.46.4", "mizchi/bit_object@0.46.4", "mizchi/bit_types@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_bitconfig/moon.mod b/modules/bitx_bitconfig/moon.mod index f5d78aba..83f006d3 100644 --- a/modules/bitx_bitconfig/moon.mod +++ b/modules/bitx_bitconfig/moon.mod @@ -3,8 +3,8 @@ name = "mizchi/bitx_bitconfig" version = "0.46.4" import { - "bobzhang/toml@0.1.7", - "moonbitlang/x@0.4.40", + "bobzhang/toml@0.4.3", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_doc/moon.mod b/modules/bitx_doc/moon.mod index 68b0ccbe..9ee33493 100644 --- a/modules/bitx_doc/moon.mod +++ b/modules/bitx_doc/moon.mod @@ -7,7 +7,7 @@ import { "mizchi/bit_object@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_osfs@0.46.4", - "moonbitlang/x@0.4.40", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_hub/moon.mod b/modules/bitx_hub/moon.mod index 28eca758..ab047fe7 100644 --- a/modules/bitx_hub/moon.mod +++ b/modules/bitx_hub/moon.mod @@ -12,9 +12,9 @@ import { "mizchi/bit_types@0.46.4", "mizchi/bit_pack@0.46.4", "mizchi/bit_protocol@0.46.4", - "mizchi/x@0.2.0", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "mizchi/x@0.6.1", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_hub/src/native/sync_native.mbt b/modules/bitx_hub/src/native/sync_native.mbt index fbc916b0..141fd7b6 100644 --- a/modules/bitx_hub/src/native/sync_native.mbt +++ b/modules/bitx_hub/src/native/sync_native.mbt @@ -1378,7 +1378,7 @@ pub async fn hub_push( None => hub_push_git_http(rfs, git_dir, remote_url) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } if should_fallback_to_relay(err, remote_url) { @@ -1490,7 +1490,7 @@ pub async fn hub_fetch( conflict_policy=effective_conflict_policy, ) catch { err => { - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } if should_fallback_to_relay(err, remote_url) { diff --git a/modules/bitx_kv/moon.mod b/modules/bitx_kv/moon.mod index fc9f0188..6b2c2747 100644 --- a/modules/bitx_kv/moon.mod +++ b/modules/bitx_kv/moon.mod @@ -11,9 +11,9 @@ import { "mizchi/bit_types@0.46.4", "mizchi/bit_vfs@0.46.4", "mizchi/bit_osfs@0.46.4", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", - "mizchi/x@0.2.0", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", + "mizchi/x@0.6.1", } readme = "src/README.md" diff --git a/modules/bitx_rebase_ai/moon.mod b/modules/bitx_rebase_ai/moon.mod index 0ab47e2d..3376b683 100644 --- a/modules/bitx_rebase_ai/moon.mod +++ b/modules/bitx_rebase_ai/moon.mod @@ -10,9 +10,9 @@ import { "mizchi/bit_runtime@0.46.4", "mizchi/bit_osfs@0.46.4", "mizchi/bit_utils@0.46.4", - "mizchi/llm@0.2.2", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "mizchi/llm@0.3.2", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_subdir/moon.mod b/modules/bitx_subdir/moon.mod index 1b21853b..bf022cc8 100644 --- a/modules/bitx_subdir/moon.mod +++ b/modules/bitx_subdir/moon.mod @@ -10,7 +10,7 @@ import { "mizchi/bit_lib@0.46.4", "mizchi/bit_types@0.46.4", "mizchi/bit_vfs@0.46.4", - "mizchi/zlib@0.4.8", + "mizchi/zlib@0.4.9", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_wal/moon.mod b/modules/bitx_wal/moon.mod index f9dd2dda..cbeb0770 100644 --- a/modules/bitx_wal/moon.mod +++ b/modules/bitx_wal/moon.mod @@ -6,7 +6,7 @@ import { "mizchi/bit_hash@0.46.4", "mizchi/bit_object@0.46.4", "mizchi/bit_objstore@0.46.4", - "moonbitlang/async@0.19.4", + "moonbitlang/async@0.22.1", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_workspace/moon.mod b/modules/bitx_workspace/moon.mod index 04b652c7..5eec1397 100644 --- a/modules/bitx_workspace/moon.mod +++ b/modules/bitx_workspace/moon.mod @@ -11,8 +11,8 @@ import { "mizchi/bit_osfs@0.46.4", "mizchi/bit_utils@0.46.4", "mizchi/bitflow@0.4.1", - "moonbitlang/async@0.19.4", - "moonbitlang/x@0.4.40", + "moonbitlang/async@0.22.1", + "moonbitlang/x@0.5.5", } repository = "https://github.com/mizchi/bit-vcs" diff --git a/modules/bitx_workspace/src/workspace.mbt b/modules/bitx_workspace/src/workspace.mbt index 0677790f..9689a69e 100644 --- a/modules/bitx_workspace/src/workspace.mbt +++ b/modules/bitx_workspace/src/workspace.mbt @@ -2124,7 +2124,7 @@ async fn handle_workspace_run(args : Array[String]) -> Unit raise Error { cwd=workspace_task_run_cwd(node_root, task_spec), ) catch { err => - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } else { 1 @@ -2524,7 +2524,7 @@ async fn handle_workspace_flow( cwd=workspace_star_task_run_cwd(workspace_root, node_map, task_spec), ) catch { err => - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } else { 1 @@ -2766,7 +2766,7 @@ async fn handle_workspace_flow( cwd=workspace_task_run_cwd(node_root, task_spec), ) catch { err => - if @async.is_being_cancelled() || @async.is_cancellation_error(err) { + if @async.is_being_cancelled() { raise err } else { 1 From c48b57b88a2a456b4969110158bdd1e1733048c7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 13:38:56 +0000 Subject: [PATCH 02/10] build: clear the warnings the 0.10.13 compiler turns into CI errors `pkf run check` runs moon check with --deny-warn, and the new compiler adds a `fragile_catch_all` lint for `catch { err => raise err }` and for cleanup done inside a catch-all handler (which no longer sees async cancellation). Drop the 60 pure re-raise handlers, move the three temp-dir / client cleanups to `errdefer`, and fix the fallout: - two merge-state cleanup helpers no longer raise, so drop `raise Error` - `@async.sleep` cannot fail any more, so the test doubles in lfs_client_wbtest stop catching it - bit_archive and bit_fast_import imported the now-empty strconv package moon check --deny-warn --warn-list=-27-20-82 passes for native, js and wasm. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- modules/bit/cmd/bit/cat.mbt | 118 +++++++++--------- modules/bit/cmd/bit/checkout.mbt | 2 +- modules/bit/cmd/bit/cherry_pick.mbt | 18 +-- modules/bit/cmd/bit/commit.mbt | 2 +- modules/bit/cmd/bit/diff.mbt | 25 ++-- modules/bit/cmd/bit/grep.mbt | 23 ++-- modules/bit/cmd/bit/interpret_trailers.mbt | 6 +- modules/bit/cmd/bit/merge.mbt | 4 +- modules/bit/cmd/bit/push.mbt | 28 ++--- modules/bit/cmd/bit/rebase.mbt | 86 ++++++++----- modules/bit/cmd/bit/rev_parse.mbt | 4 +- modules/bit/cmd/bit/subdir_ops.mbt | 26 ++-- modules/bit/cmd/bit/tree.mbt | 106 ++++++++-------- .../bit_io_native/src/http_client_native.mbt | 35 +++--- .../bit_lib/src/native/lfs_client_wbtest.mbt | 8 +- modules/bit_lib/src/subdir.mbt | 20 ++- modules/bitx_subdir/src/commit.mbt | 20 +-- modules/bitx_subdir/src/init.mbt | 8 +- modules/bitx_subdir/src/module.mbt | 20 +-- modules/bitx_subdir/src/sparse.mbt | 16 +-- modules/bitx_subdir/src/subdir.mbt | 12 +- 21 files changed, 258 insertions(+), 329 deletions(-) diff --git a/modules/bit/cmd/bit/cat.mbt b/modules/bit/cmd/bit/cat.mbt index 73f997c2..6fc42c23 100644 --- a/modules/bit/cmd/bit/cat.mbt +++ b/modules/bit/cmd/bit/cat.mbt @@ -67,71 +67,65 @@ async fn handle_cat(args : Array[String]) -> Unit raise Error { } let path = @bitlib.normalize_repo_path(raw_path) let temp_dir = make_temp_dir(fs, "bit-cat") - try { - let _ = @bitnative.clone_http_to_fs( - remote_url, - true, - fs, - temp_dir, - fs, - depth=1, - filter=@protocol.FilterSpec::BlobNone, - ) - let git_dir = temp_dir + "/.git" - let commit_id = match ref_spec { - Some(refname) => { - let resolved = resolve_remote_ref_id(remote_url, refname) - guard resolved is Some((id, _)) else { - raise @bitcore.GitError::InvalidObject("Unknown ref: " + refname) - } - id - } - None => { - let head_id = @bitrepo.rev_parse(fs, git_dir, "HEAD") - guard head_id is Some(id) else { - raise @bitcore.GitError::InvalidObject("HEAD not found") - } - id + errdefer remove_dir_recursive(fs, temp_dir) + let _ = @bitnative.clone_http_to_fs( + remote_url, + true, + fs, + temp_dir, + fs, + depth=1, + filter=@protocol.FilterSpec::BlobNone, + ) + let git_dir = temp_dir + "/.git" + let commit_id = match ref_spec { + Some(refname) => { + let resolved = resolve_remote_ref_id(remote_url, refname) + guard resolved is Some((id, _)) else { + raise @bitcore.GitError::InvalidObject("Unknown ref: " + refname) } + id } - let mut db = @bitlib.ObjectDb::load_lazy(fs, git_dir) - if db.get(fs, commit_id) is None { - let pack = @bitnative.fetch_pack_http(remote_url, [commit_id], true) - let objects = @pack.parse_packfile(pack) - @pack.write_packfile_with_index(fs, git_dir, pack, objects) - db = @bitlib.ObjectDb::load_lazy(fs, git_dir) - } - let tree_id = resolve_to_tree(db, fs, commit_id) - let entry = @bitlib.find_tree_entry(db, fs, tree_id, path) - guard entry is Some(found) else { - raise @bitcore.GitError::InvalidObject("path not found: " + path) - } - let is_tree = found.mode == "40000" || found.mode == "040000" - let is_submodule = found.mode == "160000" - if is_tree { - raise @bitcore.GitError::InvalidObject("path is a tree: " + path) - } - if is_submodule { - raise @bitcore.GitError::InvalidObject("path is a submodule: " + path) - } - let mut obj = db.get(fs, found.id) - if obj is None { - let wants : Array[@bitcore.ObjectId] = [found.id] - let pack = @bitnative.fetch_pack_http(remote_url, wants, true) - let objects = @pack.parse_packfile(pack) - @pack.write_packfile_with_index(fs, git_dir, pack, objects) - let db2 = @bitlib.ObjectDb::load_lazy(fs, git_dir) - obj = db2.get(fs, found.id) - } - guard obj is Some(blob) else { - raise @bitcore.GitError::InvalidObject("blob not found: " + path) - } - @stdio.stdout.write(blob.data) - } catch { - err => { - remove_dir_recursive(fs, temp_dir) - raise err + None => { + let head_id = @bitrepo.rev_parse(fs, git_dir, "HEAD") + guard head_id is Some(id) else { + raise @bitcore.GitError::InvalidObject("HEAD not found") + } + id } } + let mut db = @bitlib.ObjectDb::load_lazy(fs, git_dir) + if db.get(fs, commit_id) is None { + let pack = @bitnative.fetch_pack_http(remote_url, [commit_id], true) + let objects = @pack.parse_packfile(pack) + @pack.write_packfile_with_index(fs, git_dir, pack, objects) + db = @bitlib.ObjectDb::load_lazy(fs, git_dir) + } + let tree_id = resolve_to_tree(db, fs, commit_id) + let entry = @bitlib.find_tree_entry(db, fs, tree_id, path) + guard entry is Some(found) else { + raise @bitcore.GitError::InvalidObject("path not found: " + path) + } + let is_tree = found.mode == "40000" || found.mode == "040000" + let is_submodule = found.mode == "160000" + if is_tree { + raise @bitcore.GitError::InvalidObject("path is a tree: " + path) + } + if is_submodule { + raise @bitcore.GitError::InvalidObject("path is a submodule: " + path) + } + let mut obj = db.get(fs, found.id) + if obj is None { + let wants : Array[@bitcore.ObjectId] = [found.id] + let pack = @bitnative.fetch_pack_http(remote_url, wants, true) + let objects = @pack.parse_packfile(pack) + @pack.write_packfile_with_index(fs, git_dir, pack, objects) + let db2 = @bitlib.ObjectDb::load_lazy(fs, git_dir) + obj = db2.get(fs, found.id) + } + guard obj is Some(blob) else { + raise @bitcore.GitError::InvalidObject("blob not found: " + path) + } + @stdio.stdout.write(blob.data) remove_dir_recursive(fs, temp_dir) } diff --git a/modules/bit/cmd/bit/checkout.mbt b/modules/bit/cmd/bit/checkout.mbt index 3eb6896b..d75c4a57 100644 --- a/modules/bit/cmd/bit/checkout.mbt +++ b/modules/bit/cmd/bit/checkout.mbt @@ -280,7 +280,7 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error { fn checkout_cleanup_merge_state_files( fs : &@bitcore.FileSystem, git_dir : String, -) -> Unit raise Error { +) -> Unit { let files = ["MERGE_HEAD", "MERGE_MSG", "MERGE_MODE", "SQUASH_MSG"] for file in files { fs.remove_file(git_dir + "/" + file) catch { diff --git a/modules/bit/cmd/bit/cherry_pick.mbt b/modules/bit/cmd/bit/cherry_pick.mbt index d96db924..a9e83ff9 100644 --- a/modules/bit/cmd/bit/cherry_pick.mbt +++ b/modules/bit/cmd/bit/cherry_pick.mbt @@ -158,9 +158,7 @@ async fn handle_cherry_pick(args : Array[String]) -> Unit raise Error { } match subdir_info { Some((_, subdir_path, _)) => { - handle_subdir_cherry_pick(fs, root, git_dir, spec, subdir_path) catch { - err => raise err - } + handle_subdir_cherry_pick(fs, root, git_dir, spec, subdir_path) return } None => () @@ -282,18 +280,14 @@ async fn handle_subdir_cherry_pick( ) -> Unit raise Error { print_line("Cherry-picking from upstream (subdir: \{subdir_path})...") // Resolve commit - let commit_id = resolve_ref_for_subdir(fs, git_dir, spec) catch { - err => raise err - } + let commit_id = resolve_ref_for_subdir(fs, git_dir, spec) guard commit_id is Some(cid) else { raise @bitcore.GitError::InvalidObject("unknown revision: \{spec}") } // Load object database let db = @bitlib.ObjectDb::load_lazy(fs, git_dir) // Get upstream commit's subdir tree - let upstream_tree = get_subdir_tree_from_commit(db, fs, cid, subdir_path) catch { - err => raise err - } + let upstream_tree = get_subdir_tree_from_commit(db, fs, cid, subdir_path) guard upstream_tree is Some(utree) else { raise @bitcore.GitError::InvalidObject( "Subdirectory not found in commit: \{subdir_path}", @@ -304,7 +298,7 @@ async fn handle_subdir_cherry_pick( guard commit_obj is Some(co) else { raise @bitcore.GitError::InvalidObject("Cannot read commit") } - let commit_info = @bitcore.parse_commit(co.data) catch { err => raise err } + let commit_info = @bitcore.parse_commit(co.data) let parent_tree = if commit_info.parents.length() > 0 { get_subdir_tree_from_commit(db, fs, commit_info.parents[0], subdir_path) catch { _ => None @@ -329,8 +323,6 @@ async fn handle_subdir_cherry_pick( message, author, } - apply_subdir_change(fs, db, root, git_dir, change_info) catch { - err => raise err - } + apply_subdir_change(fs, db, root, git_dir, change_info) print_line("Cherry-picked: \{message}") } diff --git a/modules/bit/cmd/bit/commit.mbt b/modules/bit/cmd/bit/commit.mbt index 2605022b..ea1bc598 100644 --- a/modules/bit/cmd/bit/commit.mbt +++ b/modules/bit/cmd/bit/commit.mbt @@ -1144,7 +1144,7 @@ async fn commit_with_merge_heads( fn cleanup_merge_state_files( fs : &@bitcore.FileSystem, git_dir : String, -) -> Unit raise Error { +) -> Unit { let files = ["MERGE_HEAD", "MERGE_MSG", "MERGE_MODE", "SQUASH_MSG"] for file in files { fs.remove_file(git_dir + "/" + file) catch { diff --git a/modules/bit/cmd/bit/diff.mbt b/modules/bit/cmd/bit/diff.mbt index aa08e9a8..83d7e38c 100644 --- a/modules/bit/cmd/bit/diff.mbt +++ b/modules/bit/cmd/bit/diff.mbt @@ -1605,7 +1605,12 @@ async fn handle_diff(args : Array[String]) -> Unit raise Error { let mut rotate_to : String? = None let mut skip_to : String? = None let mut combined_specs : (String, String, String)? = None - let mut blob_pair_spec : (String, String, @bitcore.ObjectId, @bitcore.ObjectId)? = None + let mut blob_pair_spec : ( + String, + String, + @bitcore.ObjectId, + @bitcore.ObjectId, + )? = None let mut expect_orderfile = false let mut expect_output = false let mut expect_rotate_to = false @@ -1948,9 +1953,7 @@ async fn handle_diff(args : Array[String]) -> Unit raise Error { output.stat || output.shortstat || output.dirstat || output.summary, output.name_only, output.name_status, - ) catch { - err => raise err - } + ) if exit_code { // `handle_subdir_diff` writes output directly; use diff result as conservative signal. let files = if cached { @@ -1968,7 +1971,9 @@ async fn handle_diff(args : Array[String]) -> Unit raise Error { } let all_files = match blob_pair_spec { Some((old_spec, new_spec, old_id, new_id)) => - diff_blob_pair_files(rfs, repo_git_dir, old_spec, new_spec, old_id, new_id) + diff_blob_pair_files( + rfs, repo_git_dir, old_spec, new_spec, old_id, new_id, + ) None => match combined_specs { Some((base, parent_a, parent_b)) => @@ -2526,7 +2531,7 @@ async fn diff_observe_worktree_path( if rm_has_symlink_leading_path(path, root_abs, fn(abs : String) { @bitio.read_symlink_target_path(abs) is Some(_) }) { - return { mode: None, id: None } + return { mode: None, id: None, } } let abs = root + "/" + path let autocrlf = @bitlib.read_autocrlf_setting(fs, git_dir) @@ -2567,10 +2572,10 @@ async fn diff_observe_worktree_path( id: @bitlib.resolve_head_commit(fs, sub_git_dir), } } else { - { mode: None, id: None } + { mode: None, id: None, } } } else { - { mode: None, id: None } + { mode: None, id: None, } } } } @@ -3080,9 +3085,7 @@ fn diff_resolve_blob_id( git_dir : String, spec : String, ) -> @bitcore.ObjectId? raise Error { - guard @bitrepo.rev_parse(rfs, git_dir, spec) is Some(oid) else { - return None - } + guard @bitrepo.rev_parse(rfs, git_dir, spec) is Some(oid) else { return None } guard db.get(rfs, oid) is Some(obj) else { return None } if obj.obj_type == @bitcore.ObjectType::Blob { Some(oid) diff --git a/modules/bit/cmd/bit/grep.mbt b/modules/bit/cmd/bit/grep.mbt index 7ddad45d..1853b90a 100644 --- a/modules/bit/cmd/bit/grep.mbt +++ b/modules/bit/cmd/bit/grep.mbt @@ -355,9 +355,7 @@ async fn handle_grep(args : Array[String]) -> Unit raise Error { patterns, expr_tokens, use_expr, - ) catch { - err => raise err - } + ) i += 2 } "-f" => raise @bitcore.GitError::InvalidObject("fatal: no pattern given") @@ -365,9 +363,7 @@ async fn handle_grep(args : Array[String]) -> Unit raise Error { let file = String::unsafe_substring(arg, start=2, end=arg.length()) grep_append_patterns_from_file( fs, root, file, patterns, expr_tokens, use_expr, - ) catch { - err => raise err - } + ) i += 1 } "--threads" if i + 1 < args.length() => i += 2 @@ -750,7 +746,7 @@ fn grep_limit_file_matches( for i in 0.. - { header_pattern: Some(pattern), include_leading_comments: true } + { header_pattern: Some(pattern), include_leading_comments: true, } None => match funcname { Some(pattern) => - { header_pattern: Some(pattern), include_leading_comments: false } - None => { header_pattern: None, include_leading_comments: false } + { + header_pattern: Some(pattern), + include_leading_comments: false, + } + None => { header_pattern: None, include_leading_comments: false, } } } } - None => { header_pattern: None, include_leading_comments: false } + None => { header_pattern: None, include_leading_comments: false, } } } @@ -2061,7 +2060,7 @@ fn grep_prefix_file_matches( let prefixed : Array[@bitgrep.GrepFileMatch] = [] for item in matches { let path = if item.path == "" { prefix } else { prefix + "/" + item.path } - prefixed.push({ path, matches: item.matches }) + prefixed.push({ path, matches: item.matches, }) } prefixed } diff --git a/modules/bit/cmd/bit/interpret_trailers.mbt b/modules/bit/cmd/bit/interpret_trailers.mbt index 6d492fb0..e4852878 100644 --- a/modules/bit/cmd/bit/interpret_trailers.mbt +++ b/modules/bit/cmd/bit/interpret_trailers.mbt @@ -77,7 +77,7 @@ async fn handle_interpret_trailers(args : Array[String]) -> Unit raise Error { // Read input let fs = OsFs::new() let input = if positional.length() > 0 { - let file_bytes = fs.read_file(positional[0]) catch { err => raise err } + let file_bytes = fs.read_file(positional[0]) decode_bytes(file_bytes) } else { decode_bytes(read_all_stdin()) @@ -118,9 +118,7 @@ async fn handle_interpret_trailers(args : Array[String]) -> Unit raise Error { } } if in_place && positional.length() > 0 { - fs.write_file(positional[0], str_to_bytes(output)) catch { - err => raise err - } + fs.write_file(positional[0], str_to_bytes(output)) } else { print_str(output) } diff --git a/modules/bit/cmd/bit/merge.mbt b/modules/bit/cmd/bit/merge.mbt index 425374b9..4298a901 100644 --- a/modules/bit/cmd/bit/merge.mbt +++ b/modules/bit/cmd/bit/merge.mbt @@ -384,9 +384,7 @@ async fn handle_merge(args : Array[String]) -> Unit raise Error { // Check if subdir-clone and handle specially match get_subdir_info(fs, git_dir) { Some((_, subdir_path, _)) => { - handle_subdir_merge(fs, root, git_dir, refspec, subdir_path, message) catch { - err => raise err - } + handle_subdir_merge(fs, root, git_dir, refspec, subdir_path, message) return } None => () diff --git a/modules/bit/cmd/bit/push.mbt b/modules/bit/cmd/bit/push.mbt index cede8937..d1369252 100644 --- a/modules/bit/cmd/bit/push.mbt +++ b/modules/bit/cmd/bit/push.mbt @@ -288,7 +288,7 @@ fn push_append_upstream_config_update( branch_name_from_head_ref(source_ref) } match branch_name { - Some(name) => updates.push({ branch_name: name, merge_ref: dest_ref }) + Some(name) => updates.push({ branch_name: name, merge_ref: dest_ref, }) None => () } } @@ -962,9 +962,7 @@ async fn handle_push(args : Array[String]) -> Unit raise Error { } handle_subdir_push( fs, root, git_dir, remote_url, subdir_path, base_hex, first_refname, force, - ) catch { - err => raise err - } + ) if porcelain { let (flag, status) = classify_push_porcelain_success( @bitcore.ObjectId::zero(), @@ -2176,9 +2174,7 @@ async fn handle_subdir_push( // Step 3: Collect local commits since initial let local_commits = collect_commits_since( fs, git_dir, initial_commit, local_head, - ) catch { - err => raise err - } + ) if local_commits.length() == 0 { print_line("Nothing to push.") return @@ -2201,9 +2197,7 @@ async fn handle_subdir_push( for commit_id in local_commits { let new_commit = transform_subdir_commit( fs, db, git_dir, commit_id, parent, subdir_path, - ) catch { - err => raise err - } + ) print_line(" Transformed: \{commit_id.to_hex()} -> \{new_commit.to_hex()}") parent = new_commit } @@ -2295,14 +2289,14 @@ fn transform_subdir_commit( guard local_obj is Some(lo) else { raise @bitcore.GitError::InvalidObject("Cannot find local commit") } - let local_info = @bitcore.parse_commit(lo.data) catch { err => raise err } + let local_info = @bitcore.parse_commit(lo.data) let (author, message) = parse_commit_author_message(lo.data) // Get upstream parent's tree let upstream_obj = db.get(fs, upstream_parent) guard upstream_obj is Some(uo) else { raise @bitcore.GitError::InvalidObject("Cannot find upstream commit") } - let upstream_info = @bitcore.parse_commit(uo.data) catch { err => raise err } + let upstream_info = @bitcore.parse_commit(uo.data) // The local commit's tree IS the subdirectory content let new_subdir_tree = local_info.tree // Replace the subdirectory in the upstream tree @@ -2313,9 +2307,7 @@ fn transform_subdir_commit( upstream_info.tree, subdir_path, new_subdir_tree, - ) catch { - err => raise err - } + ) // Create new commit with the transformed tree let timestamp = get_current_timestamp() let new_commit = @subdir.create_commit_in_repo( @@ -2364,7 +2356,7 @@ fn replace_tree_recursive_push( guard tree_obj is Some(to) else { raise @bitcore.GitError::InvalidObject("Cannot find tree") } - let entries = @bitcore.parse_tree(to.data) catch { err => raise err } + let entries = @bitcore.parse_tree(to.data) // Build new entries let new_entries : Array[@bitcore.TreeEntry] = [] let target_name = path_parts[depth] @@ -2386,9 +2378,7 @@ fn replace_tree_recursive_push( path_parts, depth + 1, new_leaf, - ) catch { - err => raise err - } + ) new_entries.push( @bitcore.TreeEntry::new(entry.mode, entry.name, new_child), ) diff --git a/modules/bit/cmd/bit/rebase.mbt b/modules/bit/cmd/bit/rebase.mbt index 26693ce2..e33b7af9 100644 --- a/modules/bit/cmd/bit/rebase.mbt +++ b/modules/bit/cmd/bit/rebase.mbt @@ -442,7 +442,7 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { check_and_exit_unsupported_attrs(root) let wfs : &@bitcore.FileSystem = fs let rfs : &@bitcore.RepoFileSystem = fs - let filter_cmd = @bitlib.FilterCmd::{ run: @bitlibnative.run_filter_command } + let filter_cmd = @bitlib.FilterCmd::{ run: @bitlibnative.run_filter_command, } // Parse arguments let mut do_continue = false let mut do_abort = false @@ -734,9 +734,7 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { } // Check if this is a subdir-clone and handle specially if is_subdir_clone(fs, git_dir) { - handle_subdir_rebase(fs, root, git_dir, upstream) catch { - e => raise e - } + handle_subdir_rebase(fs, root, git_dir, upstream) return } // Handle --quit: drop rebase state without restoring the original branch @@ -789,7 +787,12 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { print_interactive_rebase_result(result, quiet~) } else { let state_before = @bitlib.load_rebase_state(rfs, git_dir) - let result = @bitlib.rebase_continue(fs, fs, root, run_filter_cmd=filter_cmd) + let result = @bitlib.rebase_continue( + fs, + fs, + root, + run_filter_cmd=filter_cmd, + ) let signed_id = if should_sign { match state_before { Some(state) => @@ -1090,7 +1093,13 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { ( oid, @bitlib.rebase_start_with_onto( - fs, fs, root, oid, id, force_rebase~, run_filter_cmd=filter_cmd, + fs, + fs, + root, + oid, + id, + force_rebase~, + run_filter_cmd=filter_cmd, ), ) } @@ -1112,7 +1121,12 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { ( id, @bitlib.rebase_start_with_onto( - fs, fs, root, id, exclude_from, force_rebase~, + fs, + fs, + root, + id, + exclude_from, + force_rebase~, run_filter_cmd=filter_cmd, ), ) @@ -1121,7 +1135,11 @@ async fn handle_rebase(args : Array[String]) -> Unit raise Error { if result.status is @bitlib.RebaseStatus::Conflict { wfs.write_string( git_dir + "/rebase-merge/backend", - if use_apply_backend { "apply" } else { "merge" }, + if use_apply_backend { + "apply" + } else { + "merge" + }, ) catch { _ => () } @@ -1191,14 +1209,26 @@ async fn rebase_copy_notes_after_rewrite( for notes_ref in target_refs { for pair in rewritten { let (old_id, new_id) = pair - if rebase_note_exists(rfs, git_dir, common_git_dir, notes_ref, old_id.to_hex()) { + if rebase_note_exists( + rfs, + git_dir, + common_git_dir, + notes_ref, + old_id.to_hex(), + ) { // force=true: internal rewrite copying (unlike `git notes copy`) is // not asking the user to confirm, and a rebase can deterministically // reproduce the same new commit id it produced last time (e.g. when // replaying the exact same commit onto the exact same base again), // in which case the destination note already legitimately exists. notes_copy( - wfs, rfs, git_dir, common_git_dir, notes_ref, old_id.to_hex(), new_id.to_hex(), + wfs, + rfs, + git_dir, + common_git_dir, + notes_ref, + old_id.to_hex(), + new_id.to_hex(), true, ) } @@ -1976,7 +2006,7 @@ async fn cherry_pick_commit( ) let short = String::unsafe_substring(new_commit_id.to_hex(), start=0, end=7) print_line("[\{short}] \{get_first_line(message)}") - { has_conflict: false } + { has_conflict: false, } } ///| @@ -2176,9 +2206,7 @@ async fn handle_subdir_rebase( let db = @bitlib.ObjectDb::load_lazy(fs, git_dir) let commits = find_subdir_affecting_commits( db, fs, base_hex, upstream_hex, subdir_path, - ) catch { - err => raise err - } + ) if commits.length() == 0 { print_line("Already up to date. No changes to \{subdir_path}.") update_subdir_base(fs, git_dir, upstream_hex) @@ -2188,9 +2216,7 @@ async fn handle_subdir_rebase( // Step 4: Apply each commit for commit_info in commits { print_line(" Applying: \{commit_info.message}") - apply_subdir_change(fs, db, root, git_dir, commit_info) catch { - err => raise err - } + apply_subdir_change(fs, db, root, git_dir, commit_info) } // Step 5: Update base commit update_subdir_base(fs, git_dir, upstream_hex) @@ -2225,9 +2251,7 @@ fn find_subdir_affecting_commits( _ => raise @bitcore.GitError::InvalidObject("Invalid target: " + target_hex) } // Get base subdir tree - let base_subdir = get_commit_subdir_tree(db, fs, base_id, subdir_path) catch { - err => raise err - } + let base_subdir = get_commit_subdir_tree(db, fs, base_id, subdir_path) // Walk from target to base, collect commits let commits_to_check : Array[@bitcore.ObjectId] = [] let visited : Map[String, Bool] = Map([]) @@ -2241,7 +2265,7 @@ fn find_subdir_affecting_commits( commits_to_check.push(current) let obj = db.get(fs, current) guard obj is Some(o) else { break } - let info = @bitcore.parse_commit(o.data) catch { err => raise err } + let info = @bitcore.parse_commit(o.data) if info.parents.length() == 0 { break } @@ -2276,7 +2300,7 @@ fn find_subdir_affecting_commits( continue } let (author, message) = parse_commit_author_message(o.data) - result.push({ id: commit_id, subdir_tree: tree, message, author }) + result.push({ id: commit_id, subdir_tree: tree, message, author, }) prev_tree = curr_tree } i -= 1 @@ -2293,10 +2317,8 @@ fn get_commit_subdir_tree( ) -> @bitcore.ObjectId? raise @bitcore.GitError { let obj = db.get(fs, commit_id) guard obj is Some(o) else { return None } - let info = @bitcore.parse_commit(o.data) catch { err => raise err } - find_tree_subtree(db, fs, info.tree, subdir_path) catch { - err => raise err - } + let info = @bitcore.parse_commit(o.data) + find_tree_subtree(db, fs, info.tree, subdir_path) } ///| @@ -2317,7 +2339,7 @@ fn find_tree_subtree( for part in parts { let obj = db.get(fs, current) guard obj is Some(o) else { return None } - let entries = @bitcore.parse_tree(o.data) catch { err => raise err } + let entries = @bitcore.parse_tree(o.data) let mut found = false for entry in entries { if entry.name == part { @@ -2381,9 +2403,7 @@ fn apply_subdir_change( } } // Write new tree - subdir_write_tree(db, fs, info.subdir_tree, worktree) catch { - err => raise err - } + subdir_write_tree(db, fs, info.subdir_tree, worktree) // Create commit let timestamp = get_current_timestamp() let message = info.message + "\n\n(rebased from " + info.id.to_hex() + ")\n" @@ -2463,16 +2483,14 @@ fn subdir_write_tree( ) -> Unit raise @bitcore.GitError { let obj = db.get(fs, tree_id) guard obj is Some(o) else { return } - let entries = @bitcore.parse_tree(o.data) catch { err => raise err } + let entries = @bitcore.parse_tree(o.data) for entry in entries { let path = dir + "/" + entry.name if entry.mode == "40000" || entry.mode == "040000" { fs.mkdir_p(path) catch { _ => () } - subdir_write_tree(db, fs, entry.id, path) catch { - err => raise err - } + subdir_write_tree(db, fs, entry.id, path) } else { let blob = db.get(fs, entry.id) guard blob is Some(b) else { continue } diff --git a/modules/bit/cmd/bit/rev_parse.mbt b/modules/bit/cmd/bit/rev_parse.mbt index 752fb6c4..56a62841 100644 --- a/modules/bit/cmd/bit/rev_parse.mbt +++ b/modules/bit/cmd/bit/rev_parse.mbt @@ -2070,7 +2070,7 @@ fn rev_parse_read_bisect_refs( let ref_path = bisect_dir + "/" + name let is_file = @fs.is_file(ref_path) catch { _ => false } if is_file { - let content = decode_bytes(fs.read_file(ref_path) catch { e => raise e }) + let content = decode_bytes(fs.read_file(ref_path)) let oid_hex = trim_string(content) result.push(("refs/bisect/" + name, oid_hex)) } @@ -2079,7 +2079,7 @@ fn rev_parse_read_bisect_refs( let packed_path = git_dir + "/packed-refs" let packed_exists = @fs.is_file(packed_path) catch { _ => false } if packed_exists { - let content = decode_bytes(fs.read_file(packed_path) catch { e => raise e }) + let content = decode_bytes(fs.read_file(packed_path)) for line_view in content.split("\n") { let line = trim_string(line_view.to_owned()) if line.length() == 0 || line.has_prefix("#") || line.has_prefix("^") { diff --git a/modules/bit/cmd/bit/subdir_ops.mbt b/modules/bit/cmd/bit/subdir_ops.mbt index 06921b10..ec51a599 100644 --- a/modules/bit/cmd/bit/subdir_ops.mbt +++ b/modules/bit/cmd/bit/subdir_ops.mbt @@ -25,9 +25,7 @@ async fn handle_subdir_diff( // Load object database let db = @bitlib.ObjectDb::load_lazy(fs, git_dir) // Get upstream subdir tree - let upstream_tree = get_subdir_tree_from_commit(db, fs, uid, subdir_path) catch { - err => raise err - } + let upstream_tree = get_subdir_tree_from_commit(db, fs, uid, subdir_path) guard upstream_tree is Some(utree) else { raise @bitcore.GitError::InvalidObject( "Subdirectory not found in upstream: \{subdir_path}", @@ -38,7 +36,7 @@ async fn handle_subdir_diff( guard local_obj is Some(lo) else { raise @bitcore.GitError::InvalidObject("Cannot read local HEAD") } - let local_info = @bitcore.parse_commit(lo.data) catch { err => raise err } + let local_info = @bitcore.parse_commit(lo.data) let local_tree = local_info.tree // Compare trees let diffs = compare_trees(db, rfs, utree, local_tree, "") @@ -129,7 +127,7 @@ fn compare_trees( result.push(s) } } else { - result.push({ path, kind: SubdirDiffKind::Deleted }) + result.push({ path, kind: SubdirDiffKind::Deleted, }) } } } @@ -145,7 +143,7 @@ fn compare_trees( result.push(s) } } else { - result.push({ path, kind: SubdirDiffKind::Added }) + result.push({ path, kind: SubdirDiffKind::Added, }) } Some(ea) => if e.id.to_hex() != ea.id.to_hex() { @@ -157,7 +155,7 @@ fn compare_trees( result.push(s) } } else { - result.push({ path, kind: SubdirDiffKind::Modified }) + result.push({ path, kind: SubdirDiffKind::Modified, }) } } } @@ -182,7 +180,7 @@ fn compare_trees_deleted( result.push(s) } } else { - result.push({ path, kind: SubdirDiffKind::Deleted }) + result.push({ path, kind: SubdirDiffKind::Deleted, }) } } result @@ -205,7 +203,7 @@ fn compare_trees_added( result.push(s) } } else { - result.push({ path, kind: SubdirDiffKind::Added }) + result.push({ path, kind: SubdirDiffKind::Added, }) } } result @@ -223,18 +221,14 @@ async fn handle_subdir_merge( ) -> Unit raise Error { print_line("Merging from upstream (subdir: \{subdir_path})...") // Resolve upstream ref - let upstream_id = resolve_ref_for_subdir(fs, git_dir, refspec) catch { - err => raise err - } + let upstream_id = resolve_ref_for_subdir(fs, git_dir, refspec) guard upstream_id is Some(uid) else { raise @bitcore.GitError::InvalidObject("unknown revision: \{refspec}") } // Load object database let db = @bitlib.ObjectDb::load_lazy(fs, git_dir) // Get upstream subdir tree - let upstream_tree = get_subdir_tree_from_commit(db, fs, uid, subdir_path) catch { - err => raise err - } + let upstream_tree = get_subdir_tree_from_commit(db, fs, uid, subdir_path) guard upstream_tree is Some(utree) else { raise @bitcore.GitError::InvalidObject( "Subdirectory not found in upstream: \{subdir_path}", @@ -250,7 +244,7 @@ async fn handle_subdir_merge( guard local_obj is Some(lo) else { raise @bitcore.GitError::InvalidObject("Cannot read local HEAD") } - let local_info = @bitcore.parse_commit(lo.data) catch { err => raise err } + let local_info = @bitcore.parse_commit(lo.data) let local_tree = local_info.tree // Check if already up to date if local_tree.to_hex() == utree.to_hex() { diff --git a/modules/bit/cmd/bit/tree.mbt b/modules/bit/cmd/bit/tree.mbt index 8620feda..a2d499f6 100644 --- a/modules/bit/cmd/bit/tree.mbt +++ b/modules/bit/cmd/bit/tree.mbt @@ -140,66 +140,60 @@ async fn handle_tree(args : Array[String]) -> Unit raise Error { } let normalized_filters = normalize_ls_tree_filters(path_filters, "") let temp_dir = make_temp_dir(fs, "bit-tree") - try { - let _ = @bitnative.clone_http_to_fs( - remote_url, - true, - fs, - temp_dir, - fs, - depth=1, - filter=@protocol.FilterSpec::BlobNone, - ) - let git_dir = temp_dir + "/.git" - let commit_id = match ref_spec { - Some(refname) => { - let resolved = resolve_remote_ref_id(remote_url, refname) - guard resolved is Some((id, _)) else { - raise @bitcore.GitError::InvalidObject("Unknown ref: " + refname) - } - id - } - None => { - let head_id = @bitrepo.rev_parse(fs, git_dir, "HEAD") - guard head_id is Some(id) else { - raise @bitcore.GitError::InvalidObject("HEAD not found") - } - id + errdefer remove_dir_recursive(fs, temp_dir) + let _ = @bitnative.clone_http_to_fs( + remote_url, + true, + fs, + temp_dir, + fs, + depth=1, + filter=@protocol.FilterSpec::BlobNone, + ) + let git_dir = temp_dir + "/.git" + let commit_id = match ref_spec { + Some(refname) => { + let resolved = resolve_remote_ref_id(remote_url, refname) + guard resolved is Some((id, _)) else { + raise @bitcore.GitError::InvalidObject("Unknown ref: " + refname) } + id } - let mut db = @bitlib.ObjectDb::load_lazy(fs, git_dir) - if db.get(fs, commit_id) is None { - let pack = @bitnative.fetch_pack_http(remote_url, [commit_id], true) - let objects = @pack.parse_packfile(pack) - @pack.write_packfile_with_index(fs, git_dir, pack, objects) - db = @bitlib.ObjectDb::load_lazy(fs, git_dir) - } - let tree_id = resolve_to_tree(db, fs, commit_id) - print_tree_entries( - db, - fs, - tree_id, - "", - recursive, - show_trees, - only_trees, - name_only, - false, - "", - [], - "", - normalized_filters, - None, - false, - false, - None, - ) - } catch { - err => { - remove_dir_recursive(fs, temp_dir) - raise err + None => { + let head_id = @bitrepo.rev_parse(fs, git_dir, "HEAD") + guard head_id is Some(id) else { + raise @bitcore.GitError::InvalidObject("HEAD not found") + } + id } } + let mut db = @bitlib.ObjectDb::load_lazy(fs, git_dir) + if db.get(fs, commit_id) is None { + let pack = @bitnative.fetch_pack_http(remote_url, [commit_id], true) + let objects = @pack.parse_packfile(pack) + @pack.write_packfile_with_index(fs, git_dir, pack, objects) + db = @bitlib.ObjectDb::load_lazy(fs, git_dir) + } + let tree_id = resolve_to_tree(db, fs, commit_id) + print_tree_entries( + db, + fs, + tree_id, + "", + recursive, + show_trees, + only_trees, + name_only, + false, + "", + [], + "", + normalized_filters, + None, + false, + false, + None, + ) remove_dir_recursive(fs, temp_dir) } diff --git a/modules/bit_io_native/src/http_client_native.mbt b/modules/bit_io_native/src/http_client_native.mbt index 592f986e..782b449e 100644 --- a/modules/bit_io_native/src/http_client_native.mbt +++ b/modules/bit_io_native/src/http_client_native.mbt @@ -10,7 +10,7 @@ pub struct NativeHttpClient { ///| pub fn NativeHttpClient::new() -> NativeHttpClient { - { dummy: 0 } + { dummy: 0, } } ///| @@ -167,9 +167,7 @@ async fn bit_credential_fill( ignore(stderr) return None } - let text = stdout.text() catch { - _ => "" - } + let text = stdout.text() catch { _ => "" } let mut user : String? = None let mut pass : String? = None for line_view in text.split("\n") { @@ -237,14 +235,8 @@ async fn drain_response(client : @http.Client) -> Bytes raise @bit.GitError { async fn drain_response_strict( client : @http.Client, ) -> Bytes raise @bit.GitError { - let data = try { - collect_response(client, true) - } catch { - e => { - client.close() - raise e - } - } + errdefer client.close() + let data = collect_response(client, true) client.close() data } @@ -305,15 +297,15 @@ fn to_http_headers(headers : Map[String, String]) -> @http.Headers { fn split_url_origin(url : String) -> (String, String) raise @bit.GitError { let scheme_end = match url.find("://") { Some(i) => i + 3 - None => - raise @bit.GitError::IoError("URL has no scheme: \{url}") + None => raise @bit.GitError::IoError("URL has no scheme: \{url}") } let rest = String::unsafe_substring(url, start=scheme_end, end=url.length()) match rest.find("/") { - Some(i) => ( - String::unsafe_substring(url, start=0, end=scheme_end + i), - String::unsafe_substring(url, start=scheme_end + i, end=url.length()), - ) + Some(i) => + ( + String::unsafe_substring(url, start=0, end=scheme_end + i), + String::unsafe_substring(url, start=scheme_end + i, end=url.length()), + ) None => (url, "/") } } @@ -324,7 +316,10 @@ pub async fn native_http_get( headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { let auth_headers = apply_auth_header(url, headers) - let (response, client) = @http.get_stream(url, headers=to_http_headers(auth_headers)) catch { + let (response, client) = @http.get_stream( + url, + headers=to_http_headers(auth_headers), + ) catch { e => raise @bit.GitError::IoError("HTTP GET failed: \{e}") } let data = drain_response(client) @@ -469,7 +464,7 @@ pub async fn native_objstore_send( for name, value in response.headers { out_headers[name.0] = value } - { status: response.code, headers: out_headers, body: data } + { status: response.code, headers: out_headers, body: data, } } ///| diff --git a/modules/bit_lib/src/native/lfs_client_wbtest.mbt b/modules/bit_lib/src/native/lfs_client_wbtest.mbt index ab1fdd6b..5a568cc3 100644 --- a/modules/bit_lib/src/native/lfs_client_wbtest.mbt +++ b/modules/bit_lib/src/native/lfs_client_wbtest.mbt @@ -206,9 +206,7 @@ async test "lfs_upload_pack_objects_with_http: uploads cached pointer content" { body : Bytes, headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { - @async.sleep(0) catch { - err => raise @bit.GitError::IoError(err.to_string()) - } + @async.sleep(0) if url.length() == -1 { raise @bit.GitError::IoError("unreachable") } @@ -225,9 +223,7 @@ async test "lfs_upload_pack_objects_with_http: uploads cached pointer content" { body : Bytes, headers : Map[String, String], ) -> (@bit.HttpResponse, Bytes) raise @bit.GitError { - @async.sleep(0) catch { - err => raise @bit.GitError::IoError(err.to_string()) - } + @async.sleep(0) if url.length() == -1 { raise @bit.GitError::IoError("unreachable") } diff --git a/modules/bit_lib/src/subdir.mbt b/modules/bit_lib/src/subdir.mbt index 33de5993..7d101bfc 100644 --- a/modules/bit_lib/src/subdir.mbt +++ b/modules/bit_lib/src/subdir.mbt @@ -118,10 +118,8 @@ pub fn get_subdir_tree_from_commit( ) -> @bit.ObjectId? raise @bit.GitError { let obj = db.get(fs, commit_id) guard obj is Some(o) else { return None } - let info = @bit.parse_commit(o.data) catch { err => raise err } - find_subtree(db, fs, info.tree, subdir_path) catch { - err => raise err - } + let info = @bit.parse_commit(o.data) + find_subtree(db, fs, info.tree, subdir_path) } ///| @@ -163,7 +161,7 @@ fn find_subtree( for part in parts { let obj = db.get(rfs, current) guard obj is Some(tree_obj) else { return None } - let entries = @bit.parse_tree(tree_obj.data) catch { err => raise err } + let entries = @bit.parse_tree(tree_obj.data) let mut found = false for entry in entries { if entry.name == part { @@ -191,12 +189,10 @@ pub fn collect_tree_blobs( let blobs : Array[@bit.ObjectId] = [] let obj = db.get(rfs, tree_id) guard obj is Some(tree_obj) else { return blobs } - let entries = @bit.parse_tree(tree_obj.data) catch { err => raise err } + let entries = @bit.parse_tree(tree_obj.data) for entry in entries { if entry.mode == "40000" || entry.mode == "040000" { - let sub_blobs = collect_tree_blobs(db, rfs, entry.id) catch { - err => raise err - } + let sub_blobs = collect_tree_blobs(db, rfs, entry.id) for b in sub_blobs { blobs.push(b) } @@ -217,16 +213,14 @@ pub fn write_tree_to_worktree( ) -> Unit raise @bit.GitError { let obj = db.get(rfs, tree_id) guard obj is Some(tree_obj) else { return } - let entries = @bit.parse_tree(tree_obj.data) catch { err => raise err } + let entries = @bit.parse_tree(tree_obj.data) for entry in entries { let path = dir + "/" + entry.name if entry.mode == "40000" || entry.mode == "040000" { wfs.mkdir_p(path) catch { _ => () } - write_tree_to_worktree(db, rfs, wfs, entry.id, path) catch { - err => raise err - } + write_tree_to_worktree(db, rfs, wfs, entry.id, path) } else { let blob_obj = db.get(rfs, entry.id) guard blob_obj is Some(blob) else { continue } diff --git a/modules/bitx_subdir/src/commit.mbt b/modules/bitx_subdir/src/commit.mbt index 24e7759b..00b949f9 100644 --- a/modules/bitx_subdir/src/commit.mbt +++ b/modules/bitx_subdir/src/commit.mbt @@ -58,9 +58,7 @@ pub fn SubdirRepo::commit( parent_info.tree, self.subdir_path, new_subdir_tree, - ) catch { - e => raise e - } + ) // 新しいコミットを作成 let new_commit_id = create_commit_object( fs, @@ -70,17 +68,11 @@ pub fn SubdirRepo::commit( message, author, timestamp, - ) catch { - e => raise e - } + ) // HEAD(またはブランチ参照)を更新 - update_head_ref(fs, rfs, self.git_dir, new_commit_id) catch { - e => raise e - } + update_head_ref(fs, rfs, self.git_dir, new_commit_id) // インデックスを新しいコミットに合わせて更新 - update_index_from_commit(fs, rfs, self.git_dir, new_commit_id) catch { - e => raise e - } + update_index_from_commit(fs, rfs, self.git_dir, new_commit_id) // ワーキング層をクリア self.bitfs.discard_changes() new_commit_id @@ -154,9 +146,7 @@ fn replace_tree_recursive( path_parts, depth + 1, new_leaf_tree, - ) catch { - e => raise e - } + ) new_entries.push( @bit.TreeEntry::new(entry.mode, entry.name, new_child_tree), ) diff --git a/modules/bitx_subdir/src/init.mbt b/modules/bitx_subdir/src/init.mbt index 1bdaf7b7..55eb6cbb 100644 --- a/modules/bitx_subdir/src/init.mbt +++ b/modules/bitx_subdir/src/init.mbt @@ -43,11 +43,9 @@ pub fn init_subdir( } // git ラッパースクリプトを生成 if config.create_wrapper { - create_wrapper_script(fs, subdir_abs, normalized_path) catch { - e => raise e - } + create_wrapper_script(fs, subdir_abs, normalized_path) } - { path: normalized_path, git_dir, config_path, initialized: true } + { path: normalized_path, git_dir, config_path, initialized: true, } } ///| @@ -75,7 +73,7 @@ pub fn get_subdir_info( let config_dir = git_dir + "/subdir/" + path_to_safe_name(normalized_path) let config_path = config_dir + "/config" if rfs.is_file(config_path) { - Some({ path: normalized_path, git_dir, config_path, initialized: true }) + Some({ path: normalized_path, git_dir, config_path, initialized: true, }) } else { None } diff --git a/modules/bitx_subdir/src/module.mbt b/modules/bitx_subdir/src/module.mbt index 8650f613..de0b6047 100644 --- a/modules/bitx_subdir/src/module.mbt +++ b/modules/bitx_subdir/src/module.mbt @@ -79,13 +79,9 @@ pub fn init_module( _ => () } // 7. filter driver スクリプトを作成 - setup_filter_script(fs, rfs, git_dir, normalized_path) catch { - e => raise e - } + setup_filter_script(fs, rfs, git_dir, normalized_path) // 8. .gitattributes に filter パターンを追加 - setup_gitattributes_filter(fs, rfs, repo_root, normalized_path) catch { - e => raise e - } + setup_gitattributes_filter(fs, rfs, repo_root, normalized_path) ignore(head_commit_id) } @@ -121,9 +117,7 @@ fn setup_filter_script( // .git/config に filter 設定を追加 setup_filter_config( fs, rfs, git_dir, filter_name, clean_script, smudge_script, - ) catch { - e => raise e - } + ) } ///| @@ -307,13 +301,9 @@ fn _setup_filter_driver( ) -> Unit raise SubdirError { let filter_name = "moongit-subdir-" + path_to_module_name(subdir_path) // 1. .git/config に filter を追加 - add_filter_to_config(fs, rfs, git_dir, filter_name, subdir_path) catch { - e => raise e - } + add_filter_to_config(fs, rfs, git_dir, filter_name, subdir_path) // 2. .gitattributes にパターンを追加 - add_filter_to_gitattributes(fs, rfs, repo_root, filter_name, subdir_path) catch { - e => raise e - } + add_filter_to_gitattributes(fs, rfs, repo_root, filter_name, subdir_path) } ///| diff --git a/modules/bitx_subdir/src/sparse.mbt b/modules/bitx_subdir/src/sparse.mbt index 1310bb53..eae57ce7 100644 --- a/modules/bitx_subdir/src/sparse.mbt +++ b/modules/bitx_subdir/src/sparse.mbt @@ -158,13 +158,9 @@ pub fn set_module_sparse_patterns( ) -> Unit raise SubdirError { // sparse checkout が初期化されていなければ初期化 if !is_module_sparse_enabled(rfs, git_dir, subdir_path) { - init_module_sparse(fs, rfs, git_dir, subdir_path) catch { - e => raise e - } - } - write_module_sparse_patterns(fs, git_dir, subdir_path, patterns) catch { - e => raise e + init_module_sparse(fs, rfs, git_dir, subdir_path) } + write_module_sparse_patterns(fs, git_dir, subdir_path, patterns) } ///| @@ -178,9 +174,7 @@ pub fn add_module_sparse_patterns( ) -> Unit raise SubdirError { // sparse checkout が初期化されていなければ初期化 if !is_module_sparse_enabled(rfs, git_dir, subdir_path) { - init_module_sparse(fs, rfs, git_dir, subdir_path) catch { - e => raise e - } + init_module_sparse(fs, rfs, git_dir, subdir_path) } let existing = read_module_sparse_patterns(rfs, git_dir, subdir_path) for p in new_patterns { @@ -188,9 +182,7 @@ pub fn add_module_sparse_patterns( existing.push(p) } } - write_module_sparse_patterns(fs, git_dir, subdir_path, existing) catch { - e => raise e - } + write_module_sparse_patterns(fs, git_dir, subdir_path, existing) } ///| diff --git a/modules/bitx_subdir/src/subdir.mbt b/modules/bitx_subdir/src/subdir.mbt index b94f22f8..00404bd9 100644 --- a/modules/bitx_subdir/src/subdir.mbt +++ b/modules/bitx_subdir/src/subdir.mbt @@ -171,9 +171,7 @@ pub fn SubdirRepo::from_commit( _ => raise IoError("failed to load object db") } // サブディレクトリのツリーを抽出 - let tree_id = extract_subdir_tree(db, rfs, commit_id, normalized_path) catch { - e => raise e - } + let tree_id = extract_subdir_tree(db, rfs, commit_id, normalized_path) // サブディレクトリのツリーをベースとした Fs を作成 let bitfs = @fs.Fs::from_tree(git_dir, tree_id) { @@ -213,9 +211,7 @@ pub fn SubdirRepo::from_head( _ => raise IoError("invalid commit id in HEAD") } } - SubdirRepo::from_commit(rfs, git_dir, head_id, subdir_path, config~) catch { - e => raise e - } + SubdirRepo::from_commit(rfs, git_dir, head_id, subdir_path, config~) } ///| @@ -237,9 +233,7 @@ pub fn SubdirRepo::from_branch( ) catch { _ => raise IoError("invalid commit id in branch ref") } - SubdirRepo::from_commit(rfs, git_dir, commit_id, subdir_path, config~) catch { - e => raise e - } + SubdirRepo::from_commit(rfs, git_dir, commit_id, subdir_path, config~) } ///| From e8886398aa8427107ed6515a62611c19bab2dfb7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 14:33:24 +0000 Subject: [PATCH 03/10] ci: lift the stack limit for cmd/bit debug builds on moonc 0.10.13 moonc 0.10.13's link-core pass overflows the default 8 MiB stack while building the debug configuration of modules/bit (an ICE reporting "Stack overflow"); the same step succeeds with `ulimit -s unlimited`, and the release build is unaffected. Apply that in the cmd-native-test job, which builds and tests cmd/bit in debug, and note it in AGENTS.md. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- .github/workflows/ci.yml | 5 +++++ AGENTS.md | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c571fcd4..9824a12e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -186,6 +186,10 @@ jobs: - name: Build native binary for wbtests run: | set -euo pipefail + # moonc 0.10.13's link-core pass overflows the default 8 MiB stack + # on cmd/bit's debug build (ICE: "Stack overflow"); the release + # build is unaffected. Lift the limit for this process tree. + ulimit -s unlimited moon --version moon build --target native modules/bit bin_path=$(find _build/native -maxdepth 8 -type f -name 'bit.exe' | head -1) @@ -209,6 +213,7 @@ jobs: timeout-minutes: ${{ matrix.timeout }} run: | set -euo pipefail + ulimit -s unlimited # see "Build native binary for wbtests" if [ "${{ matrix.kind }}" = "pkg" ]; then moon test --target native -p ${{ matrix.sel }} else diff --git a/AGENTS.md b/AGENTS.md index 71947ea0..79f720cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,3 +24,13 @@ toolchain to the latest release when it is older than that, so Claude Code web sessions get a working native backend automatically. `moon build --target native --release` (the `bit.exe` binary) already uses `cc`, so it is unaffected. + +On toolchain `0.10.13` the debug build of `modules/bit` (`moon build --target +native modules/bit`, and `moon test` on `cmd/bit`) makes moonc's link-core pass +overflow the default 8 MiB stack and abort with an ICE (`Error: Stack +overflow`). Run `ulimit -s unlimited` first; the release build is unaffected. + +On toolchain `0.10.13` the debug build of `modules/bit` (`moon build --target +native modules/bit`, and `moon test` on `cmd/bit`) makes moonc's link-core pass +overflow the default 8 MiB stack and abort with an ICE (`Error: Stack +overflow`). Run `ulimit -s unlimited` first; the release build is unaffected. From 7dcbac1d1a633050ba57cf10e7e29dc95438a6f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 14:38:50 +0000 Subject: [PATCH 04/10] npm: ship the JS CLI payload as an ES module moonc now emits `import` statements for the `#module("node:fs")` FFI bindings that moonbitlang/x 0.5 uses, so the JS build of modules/bit is an ES module and can no longer be loaded with `require` as bit.cjs (js-build failed with "Cannot use import statement outside a module"). Copy the payload to npm/bit.mjs instead and import it from the ESM wrapper (bit.js) and the bin script; update package.json exports/files, .gitignore and the pkf task name (sync-npm-bit-mjs) to match. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- .gitignore | 2 +- Taskfile.pkl | 18 +++++++++--------- npm/bin/bit.mjs | 12 ++---------- npm/bit.js | 11 +++-------- npm/package.json | 4 ++-- 5 files changed, 17 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index d428655e..9a81b694 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,7 @@ version.ts xxxx .bench-baseline .local -npm/bit.cjs +npm/bit.mjs npm/lib.raw.js /result apps/ diff --git a/Taskfile.pkl b/Taskfile.pkl index ba251afc..6950aad4 100644 --- a/Taskfile.pkl +++ b/Taskfile.pkl @@ -110,19 +110,19 @@ local syncNpmLibRaw: Task = new { outputs { "npm/lib.raw.js" } } -local syncNpmBitCjs: Task = new { - name = "sync-npm-bit-cjs" - description = "Copy the JS CLI payload into the checked-in npm wrapper" - cmd = "cp _build/js/release/build/mizchi/bit/bit.js npm/bit.cjs" +local syncNpmBitMjs: Task = new { + name = "sync-npm-bit-mjs" + description = "Copy the JS CLI payload (ES module) into the checked-in npm wrapper" + cmd = "cp _build/js/release/build/mizchi/bit/bit.js npm/bit.mjs" deps { buildJsCli } inputs { "_build/js/release/build/mizchi/bit/bit.js" } - outputs { "npm/bit.cjs" } + outputs { "npm/bit.mjs" } } local buildNpm: Task = new { name = "build-npm" description = "Build the JS lib + CLI and stage them into npm/ for publish" - deps { syncNpmLibRaw; syncNpmBitCjs } + deps { syncNpmLibRaw; syncNpmBitMjs } } local bundleJsLibMinimal: Task = new { @@ -295,7 +295,7 @@ local test: Task = new { deps { build syncNpmLibRaw - syncNpmBitCjs + syncNpmBitMjs bundleJsLibMinimal bundleJsLibGitOps } @@ -316,7 +316,7 @@ local testJsBuild: Task = new { cmd = "node --test tools/js-build.test.mjs tools/npm-lib.test.mjs tools/npm-cli.test.mjs tools/demo-relay.test.mjs tools/demo-editor-link.test.mjs tools/playground-commands.test.mjs tools/playground-view.test.mjs tools/flaker-affected-rules.test.mjs tools/select-affected-tests.test.mjs" deps { syncNpmLibRaw - syncNpmBitCjs + syncNpmBitMjs bundleJsLibMinimal bundleJsLibGitOps } @@ -686,7 +686,7 @@ tasks { buildJsLib buildJsCli syncNpmLibRaw - syncNpmBitCjs + syncNpmBitMjs buildNpm bundleJsLibMinimal bundleJsLibGitOps diff --git a/npm/bin/bit.mjs b/npm/bin/bit.mjs index daf94143..f6e20b36 100755 --- a/npm/bin/bit.mjs +++ b/npm/bin/bit.mjs @@ -1,11 +1,3 @@ #!/usr/bin/env node -import { createRequire } from "node:module"; -import { fileURLToPath } from "node:url"; -import { dirname, join } from "node:path"; - -const require = createRequire(import.meta.url); -const __dirname = dirname(fileURLToPath(import.meta.url)); -const bitCjs = join(__dirname, "..", "bit.cjs"); - -// MoonBit CLI output assumes CommonJS even when the package itself is ESM. -require(bitCjs); +// The MoonBit CLI payload is an ES module; importing it runs the CLI. +import "../bit.mjs"; diff --git a/npm/bit.js b/npm/bit.js index 44e28c8f..d9787d67 100644 --- a/npm/bit.js +++ b/npm/bit.js @@ -1,8 +1,3 @@ -import { createRequire } from "node:module"; -import { dirname, join } from "node:path"; -import { fileURLToPath } from "node:url"; - -const require = createRequire(import.meta.url); -const __dirname = dirname(fileURLToPath(import.meta.url)); - -export default require(join(__dirname, "bit.cjs")); +// The MoonBit CLI payload is an ES module (moonc emits `import` statements +// for its `#module("node:fs")` FFI bindings); importing it runs the CLI. +export * from "./bit.mjs"; diff --git a/npm/package.json b/npm/package.json index 58f1ee73..31a91da0 100644 --- a/npm/package.json +++ b/npm/package.json @@ -15,7 +15,7 @@ "default": "./lib.js" }, "./bit.js": "./bit.js", - "./bit.cjs": "./bit.cjs", + "./bit.mjs": "./bit.mjs", "./package.json": "./package.json" }, "publishConfig": { @@ -27,7 +27,7 @@ "files": [ "bin/", "bit.js", - "bit.cjs", + "bit.mjs", "lib.js", "lib.d.ts", "lib.raw.js", From 45363c4790235574e4d9edbd3fe159a5e91737ee Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 14:47:21 +0000 Subject: [PATCH 05/10] tools: rebaseline the minimal JS bundle guardrail for moonc 0.10.13 The tree-shaken minimal lib bundle grew from ~163.5k to 174,458 raw / 40,265 gzip bytes with the new toolchain and dependency releases (moonbitlang/x 0.5, async 0.22); the exported surface is unchanged. Raise the raw and gzip ceilings to 180k / 44k, keeping the same kind of headroom the previous bumps left. The minimal/git-ops ratio guards are untouched (now 0.56 raw, 0.54 gzip against a 0.70 ceiling). Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- tools/verify-lib-js-treeshake.mjs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/verify-lib-js-treeshake.mjs b/tools/verify-lib-js-treeshake.mjs index d905f3b7..c9df31e7 100644 --- a/tools/verify-lib-js-treeshake.mjs +++ b/tools/verify-lib-js-treeshake.mjs @@ -4,13 +4,14 @@ import { readFileSync } from "node:fs"; import { pathToFileURL } from "node:url"; // Raised from 161_000 -> 163_000 in #162 for async-rebase export plumbing -// that isn't fully tree-shaken out of the minimal bundle. Raised again here +// that isn't fully tree-shaken out of the minimal bundle. Raised to 165_000 // for the AsyncFileSystem/AsyncRepoFileSystem/AsyncHttpClient types, which -// hit the same tree-shaking limitation. Current actual size is ~163_500 -// bytes; headroom is intentional so small future additions don't require -// another guardrail bump. -const MAX_MINIMAL_RAW_BYTES = 165_000; -const MAX_MINIMAL_GZIP_BYTES = 40_000; +// hit the same tree-shaking limitation. Rebaselined again in #179 when the +// toolchain moved to moonc 0.10.13 with moonbitlang/x 0.5 / async 0.22: the +// same exports now emit ~174_500 raw / ~40_300 gzip bytes. Headroom is +// intentional so small future additions don't require another bump. +const MAX_MINIMAL_RAW_BYTES = 180_000; +const MAX_MINIMAL_GZIP_BYTES = 44_000; const MAX_MINIMAL_RATIO = 0.70; function readSize(path) { From 3a821bb99f1d88e2c7f0188d1f06e5b4eacda647 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 15:27:23 +0000 Subject: [PATCH 06/10] docs: drop the duplicated stack-limit note in AGENTS.md CLAUDE.md is a symlink to AGENTS.md, so the note was appended twice. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- AGENTS.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 79f720cb..3e163d4e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,8 +29,3 @@ On toolchain `0.10.13` the debug build of `modules/bit` (`moon build --target native modules/bit`, and `moon test` on `cmd/bit`) makes moonc's link-core pass overflow the default 8 MiB stack and abort with an ICE (`Error: Stack overflow`). Run `ulimit -s unlimited` first; the release build is unaffected. - -On toolchain `0.10.13` the debug build of `modules/bit` (`moon build --target -native modules/bit`, and `moon test` on `cmd/bit`) makes moonc's link-core pass -overflow the default 8 MiB stack and abort with an ICE (`Error: Stack -overflow`). Run `ulimit -s unlimited` first; the release build is unaffected. From a37412076e3065eea32c1ba0ee61ec1ce5817901 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 15:53:36 +0000 Subject: [PATCH 07/10] nix: refresh moon-registry and moonbit-overlay inputs The locked mooncakes index (2026-08-12) predates bobzhang/toml 0.4.3 and moonbitlang/async 0.22.1, so nix-build failed resolving the new dependency pins (`attribute '"0.4.3"' missing`). Advance moon-registry to today's index and moonbit-overlay to its current HEAD, which ships the v0.10.13+cbb11c36f toolchain the rest of CI is pinned to. moon-registry was relocked with `nix flake update`. The overlay entry was written from `nix flake prefetch` of the same revision over git (the sandbox blocks GitHub tarball downloads); the tree has no export attributes, so the NAR hash is the one the github fetcher produces. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index bfa5c1d0..2e7d229f 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "moon-registry": { "flake": false, "locked": { - "lastModified": 1786520418, - "narHash": "sha256-SQXdiy5uRgFikTrhOBViG/dJaPsVPNCEaaoBH53Toh4=", + "lastModified": 1789573452, + "narHash": "sha256-jc+KAYjTMtxPmyNeWRxkMcuJ8IXQlEVMQqKTms+Q+SI=", "ref": "refs/heads/main", - "rev": "d5bb6b1c91c629d4de1380e1e3df336d2646b840", - "revCount": 12412, + "rev": "c285ca4e76264a8f00a534c5f7d51c7b1de135ec", + "revCount": 15375, "type": "git", "url": "https://mooncakes.io/git/index" }, @@ -94,11 +94,11 @@ "treefmt-nix": "treefmt-nix" }, "locked": { - "lastModified": 1786420125, - "narHash": "sha256-0R0o7stSsajTxBZAofhAKP19jVwN3vGTAwXHyuE2xNU=", + "lastModified": 1789543568, + "narHash": "sha256-EgxiryyyEqXIfaCavS9zohmhjRVxWcykAjOgG8y1qBs=", "owner": "moonbit-community", "repo": "moonbit-overlay", - "rev": "373a7d7e793063da0feaf6ff7942852fbc9732f3", + "rev": "86fff1688a3d14856d713b2e4650097cad43fcaa", "type": "github" }, "original": { From 89309862574907781ed7f296c07bdd70e5a054f9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 15:54:44 +0000 Subject: [PATCH 08/10] nix: follow the overlay's own nixpkgs and treefmt-nix pins The new moonbit-overlay revision locks nixpkgs a831408e and treefmt-nix 27b3b12a; mirror them in the nested lock nodes so `nix build` does not have to rewrite flake.lock in CI. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018UDsHQQ4RZzjsqix2HYGBv --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 2e7d229f..2421af59 100644 --- a/flake.lock +++ b/flake.lock @@ -109,11 +109,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1785975029, - "narHash": "sha256-X44cn5rzytELc3NNoQsh0aLkjWA/QzPfc6HPQmsG3sU=", + "lastModified": 1787364730, + "narHash": "sha256-NcYt9QJfpJiF1lAyN8BDPB4EeScbPU+EwQqPiBElrpU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "70ce234312134a463ba7728e94da2486a1d237ac", + "rev": "a831408e6378bc02ebf8cc09b52c96ca86f6bab4", "type": "github" }, "original": { @@ -296,11 +296,11 @@ ] }, "locked": { - "lastModified": 1785945821, - "narHash": "sha256-NLSyTCW4K4ofhNBllt3omPasm6QpralXH1DBZOc91Dw=", + "lastModified": 1786901030, + "narHash": "sha256-WSFCsDSE5ffgD2MqzkM2CYjeFiKhRF/dJUN8uedb6YE=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "ae7910970dddc408fe6ab1c8e4b277bb21d72dc0", + "rev": "27b3b12a8e6375f28ebe122f07d230ca5459bbfa", "type": "github" }, "original": { From 93e8778edcd4bdf0a76648a44ad0c570ecad17d3 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 05:58:08 +0000 Subject: [PATCH 09/10] fix(grep): give each -o match its own column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `git grep --column -o` prints one line per match, and each line carries the column where that match starts. bit added up the *ends* of the preceding matches instead, which double-counts the gap in front of every match after the first: on `foo_mmap bar mmap` the second match starts at column 14 and bit printed 13. Upstream git had the same bug and fixed it in "grep: fix --column --only-match for 2nd and later matches" (René Scharfe, 2026-04), shipped in 2.55 — the release `third_party/git` pins. It computes `cno = bol - start + match.rm_so + 1`; tracking the offset of the unscanned remainder and adding the match's own start column is the same thing. `grep: command path cases stay compatible` shells out to the system git, so its expectation had been captured from a pre-fix git, and the shard has been failing ever since the runners moved to 2.55. It fails the same way on `main`, unrelated to this branch's dependency bump. Verified with the native debug binary, with GIT_CONFIG_* unset so the shim does not delegate to the system git (2.43 here, still pre-fix): `bit grep --column -n -o -e mmap HEAD` now reports 5 and 14 on `foo_mmap bar mmap` and 3 and 8 on `abmmapXmmap` — the true columns — where it printed 13 and 9 before. `moon check --deny-warn --warn-list=-27-20-82 --target native` passes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0134zgvUroAxAAggLS9yufPX --- modules/bit/cmd/bit/grep.mbt | 10 +++++++--- modules/bit/cmd/bit/grep_wbtest.mbt | 12 +++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/modules/bit/cmd/bit/grep.mbt b/modules/bit/cmd/bit/grep.mbt index 1853b90a..cded0ff6 100644 --- a/modules/bit/cmd/bit/grep.mbt +++ b/modules/bit/cmd/bit/grep.mbt @@ -1688,7 +1688,11 @@ async fn grep_print_only_matching( ) -> Unit { for item in file_match.matches { let mut rest = item.line - let mut column = item.column + // Offset of `rest` within the line. Every match reports its own column + // counted from the start of the line, the way git's grep does + // (`cno = bol - start + match.rm_so + 1`): adding up the ends of the + // preceding matches instead double-counts the gap in front of each one. + let mut consumed = 0 while rest != "" { let next = @bitgrep.grep_eval_expr( rest, @@ -1709,7 +1713,7 @@ async fn grep_print_only_matching( let prefix = grep_build_prefix( file_path, item.line_number, - column, + consumed + span.start_column, show_line_numbers, show_column, show_heading, @@ -1717,10 +1721,10 @@ async fn grep_print_only_matching( color_spec, ) print_line(prefix + grep_color_wrap(matched, color_spec.match_selected)) - column += span.end_column if span.end_column >= rest.length() { break } + consumed += span.end_column rest = String::unsafe_substring( rest, start=span.end_column, diff --git a/modules/bit/cmd/bit/grep_wbtest.mbt b/modules/bit/cmd/bit/grep_wbtest.mbt index 97a27670..1b1d62e3 100644 --- a/modules/bit/cmd/bit/grep_wbtest.mbt +++ b/modules/bit/cmd/bit/grep_wbtest.mbt @@ -665,16 +665,22 @@ async fn grep_wbtest_case_only_matching_with_column() -> Unit raise Error { let stdout = grep_test_git_stdout(repo_dir, [ "grep", "--column", "-n", "-o", "-e", "mmap", "HEAD", ]) + // Every match reports its own column counted from the start of the line. + // Git releases before "grep: fix --column --only-match for 2nd and later + // matches" (René Scharfe, 2026-04) summed the ends of the preceding + // matches instead, which double-counted the gap in front of each one and + // printed 13 for the second match below. The fix is in git 2.55, which + // `third_party/git` pins. @test.assert_eq( grep_trim_trailing_newline(stdout), "HEAD:file:1:5:mmap\n" + "HEAD:file:2:5:mmap\n" + "HEAD:file:3:5:mmap\n" + - "HEAD:file:3:13:mmap\n" + + "HEAD:file:3:14:mmap\n" + "HEAD:file:4:5:mmap\n" + - "HEAD:file:4:13:mmap\n" + + "HEAD:file:4:14:mmap\n" + "HEAD:file:5:5:mmap\n" + - "HEAD:file:5:13:mmap", + "HEAD:file:5:14:mmap", ) cleanup_tree(fs, root) From 44b919fb279f50d49b2960e0d82fdd28848a5b54 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 05:58:15 +0000 Subject: [PATCH 10/10] test(serve): the HTTP route keeps a repository's .git suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `serve --http: a repository resolves under the root` asserted that `http_resolve_repo("/srv/git", "/acme/app.git")` strips the suffix and answers `/srv/git/acme/app`. It never did: the resolver hands the path to `normalize_repo_root`, which folds a trailing `/.git` — a working copy's git directory — to the work tree that holds it, and leaves `.git` alone. Leaving it alone is the point. A bare repository *is* the directory `acme/app.git`, so stripping the suffix would make the normal server layout unreachable; `bit upload-pack`, `receive-pack` and `upload-archive` read a `.git` suffix the same way, and docs/scalable-git-server.md records the route as verbatim ("Repository paths are used verbatim, never percent-decoded"). So the expectation was wrong, not the resolver, and it never passed: neither function has changed since the test landed in dd09350, whose own message notes the end-to-end run had not been executed yet. Assert what the listener implements, and add the `//.git` case that `normalize_repo_root` does fold. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0134zgvUroAxAAggLS9yufPX --- modules/bit/cmd/bit/serve_http_wbtest.mbt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/bit/cmd/bit/serve_http_wbtest.mbt b/modules/bit/cmd/bit/serve_http_wbtest.mbt index adbf93d5..4330db69 100644 --- a/modules/bit/cmd/bit/serve_http_wbtest.mbt +++ b/modules/bit/cmd/bit/serve_http_wbtest.mbt @@ -39,9 +39,18 @@ fn resolved(root : String, repo : String) -> String { ///| test "serve --http: a repository resolves under the root" { - @test.assert_eq(resolved("/srv/git", "/acme/app.git"), "/srv/git/acme/app") + // The path is used as it arrives: a bare repository is the directory + // `.git`, so stripping the suffix would make the normal server + // layout unreachable. `bit upload-pack` reads a `.git` suffix the same + // way. Only a trailing `/.git` — a working copy's git directory — folds + // to the work tree that holds it. + @test.assert_eq( + resolved("/srv/git", "/acme/app.git"), + "/srv/git/acme/app.git", + ) @test.assert_eq(resolved("/srv/git/", "/acme/app"), "/srv/git/acme/app") - @test.assert_eq(resolved(".", "/app.git"), "./app") + @test.assert_eq(resolved(".", "/app.git"), "./app.git") + @test.assert_eq(resolved("/srv/git", "/acme/app/.git"), "/srv/git/acme/app") } ///|