Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add gm repo bisect #158

Merged
merged 9 commits into from
Jan 21, 2024
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
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [`gm status`](nu-git-manager/gm-status.md)
- [`gm update-cache`](nu-git-manager/gm-update-cache.md)
- [`gm report`](nu-git-manager-sugar/extra/gm-report.md)
- [`gm repo bisect`](nu-git-manager-sugar/git/gm-repo-bisect.md)
- [`gm repo branch interactive-delete`](nu-git-manager-sugar/git/gm-repo-branch-interactive-delete.md)
- [`gm repo branch wipe`](nu-git-manager-sugar/git/gm-repo-branch-wipe.md)
- [`gm repo branches`](nu-git-manager-sugar/git/gm-repo-branches.md)
Expand Down
48 changes: 48 additions & 0 deletions docs/nu-git-manager-sugar/git/gm-repo-bisect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# `gm repo bisect` (`nu-git-manager-sugar git`)
bisect a worktree by running a piece of code repeatedly

# Examples
```nushell
# find a bug that was introduced in Nushell in `nushell/nushell
gm repo bisect --good 0.89.0 --bad 4458aae {
cargo run -- -n -c "def foo [x: list<string>] { $x }; foo []"
}
```
```
724818030dd1de392c54788eab5030074d694ecd
```
---
```nushell
# avoid running the test twice more if it is expensive and you're sure
# `--good` and `--bad` are indeed "good" and "bad"
gm repo bisect --good $good --bad $bad --no-check $test
```

## Parameters
- parameter_name: test
- parameter_type: positional
- syntax_shape: closure()
- is_optional: false
- description: the code to run to check a given revision, should return a non-zero exit code for bad revisions
---
- parameter_name: good
- parameter_type: named
- syntax_shape: string
- is_optional: true
- description: the initial known "good" revision
---
- parameter_name: bad
- parameter_type: named
- syntax_shape: string
- is_optional: true
- description: the initial known "bad" revision
---
- parameter_name: no-check
- parameter_type: switch
- is_optional: true
- description: don't check if `--good` and `--bad` are indeed "good" and "bad"

## Signatures
| input | output |
| --------- | -------- |
| `nothing` | `string` |
1 change: 1 addition & 0 deletions docs/nu-git-manager-sugar/git/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


## Commands
- [`gm repo bisect`](gm-repo-bisect.md)
- [`gm repo branch interactive-delete`](gm-repo-branch-interactive-delete.md)
- [`gm repo branch wipe`](gm-repo-branch-wipe.md)
- [`gm repo branches`](gm-repo-branches.md)
Expand Down
119 changes: 119 additions & 0 deletions pkgs/nu-git-manager-sugar/nu-git-manager-sugar/git/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,122 @@ export def "gm repo query" [table: string@git-query-tables]: nothing -> table {
query git $"select * from ($table)"
}
}

# NOTE: would be cool to use the `throw-error` from `nu-git-manager`
def throw-error [
error: record<msg: string, text: string, span: record<start: int, end: int>>
]: nothing -> error {
error make {
msg: $"(ansi red_bold)($error.msg)(ansi reset)",
label: {
text: $error.text,
span: $error.span,
},
}
}

# bisect a worktree by running a piece of code repeatedly
#
# # Examples
# ```nushell
# # find a bug that was introduced in Nushell in `nushell/nushell
# gm repo bisect --good 0.89.0 --bad 4458aae {
# cargo run -- -n -c "def foo [x: list<string>] { $x }; foo []"
# }
# ```
# ```
# 724818030dd1de392c54788eab5030074d694ecd
# ```
# ---
# ```nushell
# # avoid running the test twice more if it is expensive and you're sure
# # `--good` and `--bad` are indeed "good" and "bad"
# gm repo bisect --good $good --bad $bad --no-check $test
# ```
export def "gm repo bisect" [
test: closure, # the code to run to check a given revision, should return a non-zero exit code for bad revisions
--good: string, # the initial known "good" revision
--bad: string, # the initial known "bad" revision
--no-check, # don't check if `--good` and `--bad` are indeed "good" and "bad"
]: nothing -> string {
let res = ^git rev-parse $good | complete
if $res.exit_code != 0 {
throw-error {
msg: "invalid_git_revision",
text: $"not a valid revision in current repository",
span: (metadata $good).span,
}
}

let res = ^git rev-parse $bad | complete
if $res.exit_code != 0 {
throw-error {
msg: "invalid_git_revision",
text: "not a valid revision in current repository",
span: (metadata $bad).span,
}
}

if not $no_check {
print $"checking that ($good) is good..."
^git checkout $good
try {
do $test
} catch {
throw-error {
msg: "invalid_good_revision",
text: "not a good revision",
span: (metadata $good).span,
}
}

print $"checking that ($bad) is bad..."
^git checkout $bad
let res = try {
do $test
true
} catch {
false
}
if $res {
throw-error {
msg: "invalid_bad_revision",
text: "not a bad revision",
span: (metadata $bad).span,
}
}
}

^git bisect start
^git bisect good $good
^git bisect bad $bad

print $"starting bisecting at (^git rev-parse HEAD)"

mut first_bad = ""
while $first_bad == "" {
let head = try {
do $test
"good"
} catch {
"bad"
}

let res = ^git bisect $head
let done = $res
| lines
| get 0
| parse "{hash} is the first bad commit"
| into record
| get hash?
if $done != null {
$first_bad = $done
} else {
print $res
}
}

^git bisect reset

$first_bad
}
1 change: 1 addition & 0 deletions pkgs/nu-git-manager-sugar/tests/mod.nu
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export module imports {

export def git [] {
assert imports $MODULE "git" [
"gm repo bisect",
"gm repo branch interactive-delete",
"gm repo branch wipe",
"gm repo branches",
Expand Down