Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ jobs:
uses: actions/checkout@v4
- uses: ./.github/actions/setup-nix
- name: Build
run: nix build
run: >
nix build
--override-input moon-registry git+https://mooncakes.io/git/index
--override-input moonbit-overlay git+https://github.com/moonbit-community/moonbit-overlay
- name: Smoke test
run: test -x ./result/bin/bit

Expand Down
1 change: 1 addition & 0 deletions modules/bit/moon.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"deps": {
"moonbitlang/async": "0.16.6",
"moonbitlang/x": "0.4.40",
"mizchi/simd": "0.4.1",
"mizchi/tempfile": "0.1.0",
"mizchi/llm": "0.2.2",
"mizchi/bitflow": "0.4.0",
Expand Down
14 changes: 14 additions & 0 deletions modules/bit/src/cmd/bit/checkout.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error {
let mut track_branch = false
let mut detach_head = false
let mut quiet = false
let mut autostash = false
let pre_separator_targets : Array[String] = []
let post_separator_targets : Array[String] = []
let mut i = 0
Expand All @@ -31,6 +32,7 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error {
"-f" | "--force" => force_checkout = true
"--detach" => detach_head = true
"--orphan" => orphan_branch = true
"-m" | "--merge" => autostash = true
"-" =>
if saw_separator {
post_separator_targets.push(arg)
Expand Down Expand Up @@ -58,6 +60,7 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error {
raise @bitcore.GitError::InvalidObject("No target specified for checkout")
}
ignore(quiet)
ignore(autostash) // resolved below at branch-switch site
if is_bare_repo_dir(root) {
raise @bitcore.GitError::InvalidObject(
"this operation must be run in a work tree",
Expand Down Expand Up @@ -204,6 +207,14 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error {
let mut switched_head = false
let mut switched_head_id : @bitcore.ObjectId? = None
let mut switched_target : String? = None
// -m/--merge: stash uncommitted changes, restore after switch
let mut did_autostash = false
if autostash {
let author = get_author_string()
let timestamp = get_commit_timestamp()
let stash_id = @bitlib.stash_push(fs, fs, root, "", author, timestamp)
did_autostash = stash_id is Some(_)
}
if is_path && is_branch {
// Ambiguous - default to branch (like git)
match checkout_branch_in_use_path(rfs, root, target) {
Expand Down Expand Up @@ -244,6 +255,9 @@ async fn handle_checkout(args : Array[String]) -> Unit raise Error {
_ => ()
}
save_previous_checkout_location(fs, git_dir, previous_location)
if did_autostash {
@bitlib.stash_apply(fs, fs, root, 0, true)
}
}
} else {
let first = resolve_checkout_target(rfs, git_dir, targets[0])
Expand Down
2 changes: 1 addition & 1 deletion modules/bit/src/cmd/bit/handlers_remote_push_wbtest.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ test "push-lease: remote tracking refname follows pushed remote" {

///|
fn serve_lfs_wbtest_sha256_hex(data : Bytes) -> String {
let raw = @bithash.sha256_raw(data)
let raw = @bithash.sha256_bytes(data)
let digits = "0123456789abcdef"
let out = StringBuilder::new()
for b in raw {
Expand Down
27 changes: 27 additions & 0 deletions modules/bit/src/cmd/bit/rev_list.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ async fn handle_rev_list(args : Array[String]) -> Unit raise Error {
let mut min_parents : Int? = None
let mut graph = false
let mut no_walk = false
let mut maximal_only = false
let refs : Array[String] = []
let excludes : Array[String] = []
let symmetric_ranges : Array[(String, String)] = []
Expand Down Expand Up @@ -155,6 +156,7 @@ async fn handle_rev_list(args : Array[String]) -> Unit raise Error {
}
"--no-walk" | "--no-walk=sorted" | "--no-walk=unsorted" => no_walk = true
"--do-walk" => no_walk = false
"--maximal-only" => maximal_only = true
"--merges" => min_parents = Some(2)
"--no-merges" => max_parents = Some(1)
"--min-parents" if i + 1 < args.length() => {
Expand Down Expand Up @@ -714,6 +716,31 @@ async fn handle_rev_list(args : Array[String]) -> Unit raise Error {
result.push(id)
}
}
// --maximal-only: keep only commits not reachable from any other in result
if maximal_only {
let result_ids = result.copy()
let filtered : Array[@bitcore.ObjectId] = []
for i2 in 0..<result_ids.length() {
let candidate = result_ids[i2]
let mut dominated = false
for j in 0..<result_ids.length() {
if i2 == j {
continue
}
if @bitlib.merge_base_is_ancestor(db, fs, candidate, result_ids[j]) {
dominated = true
break
}
}
if !dominated {
filtered.push(candidate)
}
}
result.clear()
for id in filtered {
result.push(id)
}
}
// Apply ordering. git defaults to date order (committer timestamp desc).
if topo_order {
rev_list_topo_sort(db, fs, result)
Expand Down
22 changes: 22 additions & 0 deletions modules/bit_hash/bench/cmd/sha_hash/main.mbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SHA-1 / SHA-256 workload for moon-pprof profiling.

fn make_payload(len : Int) -> Bytes {
Bytes::makei(len, fn(i) { ((i * 31 + 7) % 251).to_byte() })
}

fn main {
let p64 = make_payload(64)
let p1k = make_payload(1024)
let p8k = make_payload(8192)
let p64k = make_payload(65536)
let payloads = [p64, p1k, p8k, p64k]
let mut sink = 0
for _ in 0..<500 {
for p in payloads {
let h1 = @simdhash.sha1(p)
let h2 = @simdhash.sha256(p)
sink = sink + h1[0].to_int() + h2[0].to_int()
}
}
println(sink)
}
7 changes: 7 additions & 0 deletions modules/bit_hash/bench/cmd/sha_hash/moon.pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {
"mizchi/simd/src/simdhash" @simdhash,
}

options(
"is-main": true,
)
8 changes: 8 additions & 0 deletions modules/bit_hash/bench/moon.mod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "mizchi/sha_bench",
"version": "0.1.0",
"deps": {
"mizchi/simd": "0.4.1"
},
"source": "cmd"
}
11 changes: 8 additions & 3 deletions modules/bit_hash/moon.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
"name": "mizchi/bit_hash",
"version": "0.42.2",
"deps": {
"moonbitlang/x": "0.4.40"
"mizchi/simd": "0.4.1"
},
"repository": "https://github.com/mizchi/bit-vcs",
"license": "Apache-2.0",
"keywords": ["git", "hash", "sha1", "sha256"],
"keywords": [
"git",
"hash",
"sha1",
"sha256"
],
"description": "Git object hashing primitives (gix-hash equivalent)",
"source": "src",
"preferred-target": "native"
}
}
8 changes: 8 additions & 0 deletions modules/bit_hash/src/bench_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ test "bench sha1_raw 64 KiB" (b : @bench.T) {
})
}

///|
test "bench sha256_raw 64 bytes" (b : @bench.T) {
b.bench(fn() {
let h = sha256_raw(bench_input_64)
b.keep(h.length())
})
}

///|
test "bench sha256_raw 1 KiB" (b : @bench.T) {
b.bench(fn() {
Expand Down
24 changes: 24 additions & 0 deletions modules/bit_hash/src/hex.mbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
///| Common hash/hex helpers.

///|
fn utf8_encode(s : String) -> Bytes {
let buf : Array[Byte] = []
for c in s {
let cp = c.to_int()
if cp < 0x80 {
buf.push(cp.to_byte())
} else if cp < 0x800 {
buf.push((0xc0 | (cp >> 6)).to_byte())
buf.push((0x80 | (cp & 0x3f)).to_byte())
} else if cp < 0x10000 {
buf.push((0xe0 | (cp >> 12)).to_byte())
buf.push((0x80 | ((cp >> 6) & 0x3f)).to_byte())
buf.push((0x80 | (cp & 0x3f)).to_byte())
} else {
buf.push((0xf0 | (cp >> 18)).to_byte())
buf.push((0x80 | ((cp >> 12) & 0x3f)).to_byte())
buf.push((0x80 | ((cp >> 6) & 0x3f)).to_byte())
buf.push((0x80 | (cp & 0x3f)).to_byte())
}
}
Bytes::from_array(buf)
}

///|
pub fn short_hex(hex : String, n : Int) -> String {
if hex.length() <= n {
Expand Down
11 changes: 8 additions & 3 deletions modules/bit_hash/src/moon.pkg
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
"moonbitlang/core/encoding/utf8" @utf8,
"moonbitlang/x/crypto" @crypto,
"mizchi/simd/src/simdhash" @simdhash,
}

import {
Expand All @@ -10,7 +9,13 @@ import {
warnings = "-29"

options(
"native-stub": [ "sha1_ni.c", "sha256_ni.c" ],
targets: {
"bench_test.mbt": [ "native" ],
"sha1_ni_ffi.mbt": [ "native" ],
"sha1_native_impl.mbt": [ "native" ],
"sha256_native_impl.mbt": [ "native" ],
"sha1_impl.mbt": [ "wasm", "wasm-gc", "js" ],
"sha256_impl.mbt": [ "wasm", "wasm-gc", "js" ],
"bench_test.mbt": [ "native" ],
},
)
85 changes: 1 addition & 84 deletions modules/bit_hash/src/sha1.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,6 @@ let sha1_h3 : Int = 0x10325476
///|
let sha1_h4 : Int = 0xc3d2e1f0

///|
let sha1_k0 : Int = 0x5a827999

///|
let sha1_k1 : Int = 0x6ed9eba1

///|
let sha1_k2 : Int = 0x8f1bbcdc

///|
let sha1_k3 : Int = 0xca62c1d6

///|
fn rotl32(x : Int, n : Int) -> Int {
((x << n) | (x.reinterpret_as_uint() >> (32 - n)).reinterpret_as_int()) &
0xffffffff
}

///|
pub struct Sha1State {
h : FixedArray[Int]
Expand Down Expand Up @@ -64,67 +46,6 @@ pub fn Sha1State::reset(self : Sha1State) -> Unit {
self.total_len = 0L
}

///|
fn Sha1State::process_block(self : Sha1State) -> Unit {
let h = self.h
let w = self.w
let block = self.block
for i = 0; i < 16; i = i + 1 {
w[i] = (block[i * 4].to_int() << 24) |
(block[i * 4 + 1].to_int() << 16) |
(block[i * 4 + 2].to_int() << 8) |
block[i * 4 + 3].to_int()
}
for i in 16..<80 {
w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1)
}
let mut a = h[0]
let mut b = h[1]
let mut c = h[2]
let mut d = h[3]
let mut e = h[4]
for i = 0; i < 20; i = i + 1 {
let f = (b & c) | (b.lnot() & d)
let temp = (rotl32(a, 5) + f + e + sha1_k0 + w[i]) & 0xffffffff
e = d
d = c
c = rotl32(b, 30)
b = a
a = temp
}
for i = 20; i < 40; i = i + 1 {
let f = b ^ c ^ d
let temp = (rotl32(a, 5) + f + e + sha1_k1 + w[i]) & 0xffffffff
e = d
d = c
c = rotl32(b, 30)
b = a
a = temp
}
for i = 40; i < 60; i = i + 1 {
let f = (b & c) | (b & d) | (c & d)
let temp = (rotl32(a, 5) + f + e + sha1_k2 + w[i]) & 0xffffffff
e = d
d = c
c = rotl32(b, 30)
b = a
a = temp
}
for i = 60; i < 80; i = i + 1 {
let f = b ^ c ^ d
let temp = (rotl32(a, 5) + f + e + sha1_k3 + w[i]) & 0xffffffff
e = d
d = c
c = rotl32(b, 30)
b = a
a = temp
}
h[0] = (h[0] + a) & 0xffffffff
h[1] = (h[1] + b) & 0xffffffff
h[2] = (h[2] + c) & 0xffffffff
h[3] = (h[3] + d) & 0xffffffff
h[4] = (h[4] + e) & 0xffffffff
}

///|
pub fn Sha1State::update(self : Sha1State, data : Bytes) -> Unit {
Expand Down Expand Up @@ -169,7 +90,7 @@ pub fn Sha1State::update_byte(self : Sha1State, b : Byte) -> Unit {

///|
pub fn Sha1State::update_string(self : Sha1State, s : String) -> Unit {
self.update(@utf8.encode(s))
self.update(utf8_encode(s))
}

///|
Expand Down Expand Up @@ -222,10 +143,6 @@ pub fn sha1_prefix_raw(data : Bytes, len : Int) -> FixedArray[Byte] {
state.finish_raw()
}

///|
pub fn sha1_raw(data : Bytes) -> FixedArray[Byte] {
sha1_prefix_raw(data, data.length())
}

///|
pub fn sha1_array_prefix_raw(data : Array[Byte], len : Int) -> FixedArray[Byte] {
Expand Down
Loading
Loading