diff --git a/src/cli.zig b/src/cli.zig index f7ca5da..3c7b747 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -49,8 +49,13 @@ pub fn run() !void { var staged = false; var stat = false; var has_unknown_flags = false; + var has_unsupported_native_args = false; for (args[2..]) |arg| { + if ((std.mem.eql(u8, cmd, "branch") or std.mem.eql(u8, cmd, "b")) and arg.len > 0 and arg[0] != '-') { + has_unsupported_native_args = true; + } + if (std.mem.eql(u8, arg, "-H") or std.mem.eql(u8, arg, "--human")) { human = true; } else if ((std.mem.eql(u8, arg, "-s") or std.mem.eql(u8, arg, "--staged")) and (std.mem.eql(u8, cmd, "diff") or std.mem.eql(u8, cmd, "d"))) { @@ -73,8 +78,10 @@ pub fn run() !void { } } - // If we see flags we don't handle, let git deal with it - if (has_unknown_flags) { + // If we see flags or positional forms we don't handle, let git deal with it. + // Native branch currently implements list-only output; creation/deletion args + // must pass through so `nit branch ` behaves exactly like git. + if (has_unknown_flags or has_unsupported_native_args) { try w.flush(); return passthrough(args); } diff --git a/src/cmd/log.zig b/src/cmd/log.zig index 9db0b52..8d4a1b3 100644 --- a/src/cmd/log.zig +++ b/src/cmd/log.zig @@ -28,7 +28,7 @@ pub fn run(repo: *c.git_repository, human: bool, count: usize, w: *Writer) !void const raw_summary = c.git_commit_summary(commit); const summary: []const u8 = if (raw_summary != null) std.mem.span(raw_summary) else "(empty)"; - var oid_buf: [c.GIT_OID_SHA1_HEXSIZE + 1]u8 = undefined; + var oid_buf: [c.GIT_OID_HEXSZ + 1]u8 = undefined; _ = c.git_oid_tostr(&oid_buf, oid_buf.len, &oid); const short_hash = oid_buf[0..7]; diff --git a/src/cmd/show.zig b/src/cmd/show.zig index 58db90b..e822f28 100644 --- a/src/cmd/show.zig +++ b/src/cmd/show.zig @@ -38,7 +38,7 @@ pub fn run(repo: *c.git_repository, human: bool, stat: bool, rev: ?[]const u8, w try git.check(c.git_commit_lookup(&commit, repo, &oid)); defer c.git_commit_free(commit); - var oid_buf: [c.GIT_OID_SHA1_HEXSIZE + 1]u8 = undefined; + var oid_buf: [c.GIT_OID_HEXSZ + 1]u8 = undefined; _ = c.git_oid_tostr(&oid_buf, oid_buf.len, &oid); const short_hash = oid_buf[0..7]; const raw_summary = c.git_commit_summary(commit); diff --git a/tests/conformance.sh b/tests/conformance.sh index b636617..0b82838 100755 --- a/tests/conformance.sh +++ b/tests/conformance.sh @@ -26,7 +26,7 @@ TMPDIR=$(mktemp -d -t nit-conformance-XXXXXX) trap "rm -rf $TMPDIR" EXIT cd "$TMPDIR" -git init -q +git init -q -b main git config user.email "test@test.com" git config user.name "Test User" @@ -205,6 +205,10 @@ check "branch passthrough" \ "git branch" \ "$NIT branch" +check "branch create passthrough" \ + "git branch git-created HEAD~1 >/dev/null && git branch --list git-created | sed 's/git-created/created/'" \ + "$NIT branch nit-created HEAD~1 >/dev/null && git branch --list nit-created | sed 's/nit-created/created/'" + check "log --graph passthrough" \ "git log --graph --oneline -3" \ "$NIT log --graph --oneline -3" @@ -383,7 +387,7 @@ check "show --stat initial commit has additions" \ # Stat per-file totals add up to summary check "show --stat totals consistent" \ - "$NIT show --stat $FIRST_HASH 2>&1 | tail -n +3 | grep -o '+[0-9]*' | tr -d '+' | paste -sd+ - | bc" \ + "$NIT show --stat $FIRST_HASH 2>&1 | tail -n +3 | grep -o '+[0-9]*' | tr -d '+' | awk '{s += \$1} END {print s}'" \ "$NIT show --stat $FIRST_HASH 2>&1 | sed -n '2p' | grep -o '+[0-9]*' | tr -d '+'" # --- Merge commit --- @@ -724,20 +728,36 @@ printf '\x00\x01\x02\x03BINARY\xff\xfe' > binary.dat git add binary.dat git commit -q -m "Add binary file" check "show HEAD:binary.dat matches git" \ - "git show HEAD:binary.dat | xxd" \ - "$NIT show HEAD:binary.dat 2>&1 | xxd" + "git show HEAD:binary.dat | od -An -tx1" \ + "$NIT show HEAD:binary.dat 2>&1 | od -An -tx1" # --- NIT_COLORS env var --- echo "" echo "NIT_COLORS:" -# On macOS, script -q /dev/null forces a pseudo-TTY -# Verify that NIT_COLORS changes output when running in a TTY +# Force a pseudo-TTY for color assertions. util-linux script uses -c; +# BSD/macOS script accepts the command after the typescript path. if command -v script >/dev/null 2>&1; then - # Without NIT_COLORS: default colors in TTY - default_out=$(script -q /dev/null $NIT show -H 2>&1 | cat -v | head -3) - # With NIT_COLORS: custom hash color (magenta = 35) - custom_out=$(script -q /dev/null env NIT_COLORS="hash=35" $NIT show -H 2>&1 | cat -v | head -3) + SCRIPT_USES_C_FLAG=0 + if script -q -c "printf test" /dev/null >/dev/null 2>&1; then + SCRIPT_USES_C_FLAG=1 + fi + + script_tty() { + if [ "$SCRIPT_USES_C_FLAG" = 1 ]; then + local cmd="" + local arg + for arg in "$@"; do + cmd="$cmd $(printf '%q' "$arg")" + done + script -q -c "${cmd# }" /dev/null 2>&1 + else + script -q /dev/null "$@" 2>&1 + fi + } + + default_out=$(script_tty "$NIT" show -H | cat -v | head -3) + custom_out=$(script_tty env NIT_COLORS="hash=35" "$NIT" show -H | cat -v | head -3) if [ "$default_out" != "$custom_out" ]; then PASS=$((PASS + 1)) @@ -775,7 +795,7 @@ if command -v script >/dev/null 2>&1; then "NIT_COLORS='hash=38;2;255;165;0' $NIT log -n 1 2>&1" # Verify true-color actually produces escape sequence in TTY - truecolor_out=$(script -q /dev/null env NIT_COLORS="hash=38;2;255;0;0" $NIT show -H 2>&1 | cat -v | head -1) + truecolor_out=$(script_tty env NIT_COLORS="hash=38;2;255;0;0" "$NIT" show -H | cat -v | head -1) if echo "$truecolor_out" | grep -q '38;2;255;0;0'; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS true-color escape in TTY output" @@ -797,8 +817,8 @@ if command -v script >/dev/null 2>&1; then "NIT_COLORS='boguskey=32' $NIT log -n 1 2>&1" # Duplicate keys (last wins) - verify output changes with second value - dup_out1=$(script -q /dev/null env NIT_COLORS="hash=35" $NIT show -H 2>&1 | cat -v | head -1) - dup_out2=$(script -q /dev/null env NIT_COLORS="hash=33:hash=35" $NIT show -H 2>&1 | cat -v | head -1) + dup_out1=$(script_tty env NIT_COLORS="hash=35" "$NIT" show -H | cat -v | head -1) + dup_out2=$(script_tty env NIT_COLORS="hash=33:hash=35" "$NIT" show -H | cat -v | head -1) if [ "$dup_out1" = "$dup_out2" ]; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS duplicate keys (last wins)" @@ -836,7 +856,7 @@ if command -v script >/dev/null 2>&1; then "NIT_COLORS='add=31:del=32:hunk=33:context=34:staged=35:unstaged=36:hash=37:date=38:add=39:del=40:hunk=41:context=42' $NIT log -n 1 2>&1" # NIT_COLORS affects show -H (color slot: hash, date used in show) - custom_show=$(script -q /dev/null env NIT_COLORS="hash=35" $NIT show -H 2>&1 | cat -v | head -1) + custom_show=$(script_tty env NIT_COLORS="hash=35" "$NIT" show -H | cat -v | head -1) if [ "$default_out" != "$custom_show" ] || echo "$custom_show" | grep -q '35m'; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS affects show -H" @@ -847,8 +867,8 @@ if command -v script >/dev/null 2>&1; then fi # NIT_COLORS affects diff -H (color slot: add, del, hunk, context) - default_diff=$(script -q /dev/null $NIT diff -H 2>&1 | cat -v | head -3) - custom_diff=$(script -q /dev/null env NIT_COLORS="add=35:del=36" $NIT diff -H 2>&1 | cat -v | head -3) + default_diff=$(script_tty "$NIT" diff -H | cat -v | head -3) + custom_diff=$(script_tty env NIT_COLORS="add=35:del=36" "$NIT" diff -H | cat -v | head -3) if [ "$default_diff" != "$custom_diff" ]; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS affects diff -H" @@ -859,8 +879,8 @@ if command -v script >/dev/null 2>&1; then fi # NIT_COLORS affects log -H (color slot: hash, date) - default_log=$(script -q /dev/null $NIT log -H -n 1 2>&1 | cat -v | head -1) - custom_log=$(script -q /dev/null env NIT_COLORS="hash=35:date=36" $NIT log -H -n 1 2>&1 | cat -v | head -1) + default_log=$(script_tty "$NIT" log -H -n 1 | cat -v | head -1) + custom_log=$(script_tty env NIT_COLORS="hash=35:date=36" "$NIT" log -H -n 1 | cat -v | head -1) if [ "$default_log" != "$custom_log" ]; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS affects log -H" @@ -871,8 +891,8 @@ if command -v script >/dev/null 2>&1; then fi # NIT_COLORS affects status -H (color slot: staged, unstaged) - default_status=$(script -q /dev/null $NIT status -H 2>&1 | cat -v) - custom_status=$(script -q /dev/null env NIT_COLORS="staged=35:unstaged=36" $NIT status -H 2>&1 | cat -v) + default_status=$(script_tty "$NIT" status -H | cat -v) + custom_status=$(script_tty env NIT_COLORS="staged=35:unstaged=36" "$NIT" status -H | cat -v) if [ "$default_status" != "$custom_status" ]; then PASS=$((PASS + 1)) echo " PASS: NIT_COLORS affects status -H"