Skip to content

test issue 2#149

Closed
host6 wants to merge 1 commit into
untillpro:mainfrom
host6:test-issue-2-pr
Closed

test issue 2#149
host6 wants to merge 1 commit into
untillpro:mainfrom
host6:test-issue-2-pr

Conversation

@host6

@host6 host6 commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

test issue 2

@host6 host6 closed this Jun 10, 2026
@augmentcode

augmentcode Bot commented Jun 10, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR refactors how qs dev gathers repository metadata and adds a few utility/benchmark updates.

Changes:

  • Introduced gitcmds.RepoContext and LoadRepoContext() to gather key repo state (org/repo, branch info, upstream presence, dirty state) with fewer round-trips via concurrent git calls.
  • Refactored parent-repo lookup into getParentRepoByOrgRepo() and updated GetParentRepoName() to use it.
  • Updated internal/commands/Dev() to use the new repo context (including fork/upstream workflow decisions).
  • Extended status parsing to treat AD as a special case.
  • Added benchmarks for git remote lookup and slice append preallocation patterns.
  • Bumped Go toolchain version and updated several module dependencies.

Technical Notes: LoadRepoContext() performs 5 local git queries in parallel, then performs a single GitHub API call (via gh) once org/repo are known.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread gitcmds/gitcmds.go
}

// getParentRepoByOrgRepo fetches the parent repository full name via the GitHub API.
func getParentRepoByOrgRepo(wd, org, repo string) (string, error) {

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitcmds/gitcmds.go:483 — gh api ... --jq .parent.full_name typically prints the literal string null for non-forks, and since callers check len(parentRepo) this would be treated as a real parent repo and can flip qs dev into the wrong workflow mode.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread gitcmds/status.go
oldSize = newFileSize
case `??`:
newFileSize, err2 = getFileSize(wd, name)
case `AD`:

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitcmds/status.go:168 — Porcelain status AD means “added in index, deleted in working tree”; skipping it entirely may cause qs status to miss a staged addition (and underreport/incorrectly summarize changes).

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Comment thread utils/semver.go
ar []int
}

func (bs badStruct) add( i int) {

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils/semver.go:22 — func (bs badStruct) add(...) uses a value receiver, so appending to bs.ar won’t be visible to the caller and is very likely to behave incorrectly if this ever gets used.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diagnostic: posting single comment to check

Comment thread utils/semver.go
}

func (bs badStruct) add( i int) {
bs.ar = append(bs.ar, i)

@augmentcode augmentcode Bot Jun 10, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(internal diagnostic — superseded; ignore)

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep Reviewer report

Severity counts

  • Critical: 1
  • Major: 1
  • Minor: 4

Verdict: request changes before merging.

Criticalutils/semver.go: a badStruct type with a broken value-receiver add method has been committed. It looks like leftover debug/teaching code, is unused anywhere in the codebase, and the method silently loses appended elements. It must be removed.

Majorinternal/commands/dev_test.go::BenchmarkGitLsRemote shells out to git ls-remote --heads origin main, which requires (a) network access and (b) an origin remote pointing at a reachable repository. This will fail in sandboxed / airgapped CI and is benchmarking the git CLI itself rather than any project code. Drop it or gate it behind a build tag / testing.Short().

Minor — see inline:

  1. utils/utils_test.go: a pair of generic slice-growth benchmarks unrelated to package functionality.
  2. internal/commands/dev.go: a stale // Check if upstream remote exists comment left behind by the refactor.
  3. internal/commands/dev_test.go: out[:len(out)-1] in repoRoot panics on empty git rev-parse output.
  4. gitcmds/context.go: LoadRepoContext returns on the first error received from the goroutines, silently dropping any subsequent errors and giving the user no indication of which of the five git calls failed.

Diff and supporting code reviewed at head SHA 572becbb. The PR was closed before this review completed — findings are still posted in case the branch is reopened or the changes are revived in a follow-up PR.

Comment thread utils/semver.go
Comment on lines +18 to +24
type badStruct struct {
ar []int
}

func (bs badStruct) add( i int) {
bs.ar = append(bs.ar, i)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical — debug/dead code with a real bug.

badStruct is not referenced anywhere in the codebase, has no tests, and the add method uses a value receiver, so bs.ar = append(bs.ar, i) mutates a local copy and the appended element is lost the moment the method returns. Either the type is genuinely needed (in which case add must take a pointer receiver, and a real use plus tests should accompany it) or — much more likely from the name and the lack of callers — this is leftover scratch code that should not be merged.

There is also a stray space in the parameter list: add( i int).

Recommended action: delete the badStruct block (lines 18–24) in its entirety.

Comment on lines +10 to +20
func BenchmarkGitLsRemote(b *testing.B) {
wd := repoRoot(b)
b.ResetTimer()
for b.Loop() {
cmd := exec.Command("git", "ls-remote", "--heads", "origin", "main")
cmd.Dir = wd
out, err := cmd.Output()
require.NoError(b, err)
_ = out
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major — benchmark depends on network and external git state.

git ls-remote --heads origin main performs a network round-trip to whatever URL origin points at. This benchmark therefore:

  1. Fails outright in any environment without network access (sandboxed CI, airgapped builds, go test ./... on a checkout without origin).
  2. Measures network latency to GitHub plus the git CLI cost — not anything in this package.
  3. require.NoError(b, err) in a benchmark turns a transient network blip into a hard test failure for unrelated CI jobs (go test -bench is sometimes run alongside go test).

If the intent is to compare local strategies for branch-existence checks, point at a local fixture repo (e.g. git init in a t.TempDir() and add a local origin), or gate the benchmark behind if testing.Short() { b.Skip(...) } and a build tag such as //go:build network.

b.Helper()
out, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
require.NoError(b, err)
return string(out[:len(out)-1]) // trim trailing newline

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor — potential panic on empty output.

out[:len(out)-1] panics with a slice-bounds-out-of-range error if git rev-parse --show-toplevel ever returns an empty buffer (for example if the helper is reused in a non-git directory but git still exits 0). Safer:

Suggested change
return string(out[:len(out)-1]) // trim trailing newline
return strings.TrimRight(string(out), "\n")

(and add "strings" to the imports).

Comment thread utils/utils_test.go
Comment on lines +14 to +38
// BenchmarkAppendNoPrealloc demonstrates ineffective array usage:
// every append that exceeds capacity causes a full slice reallocation and copy.
func BenchmarkAppendNoPrealloc(b *testing.B) {
const n = 10_000
for b.Loop() {
s := []int{}
for i := range n {
s = append(s, i)
}
_ = s
}
}

// BenchmarkAppendPrealloc shows the effective alternative:
// a single allocation with make avoids all intermediate copies.
func BenchmarkAppendPrealloc(b *testing.B) {
const n = 10_000
for b.Loop() {
s := make([]int, 0, n)
for i := range n {
s = append(s, i)
}
_ = s
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor — benchmarks unrelated to package code.

BenchmarkAppendNoPrealloc / BenchmarkAppendPrealloc measure generic Go slice-growth behavior, not anything from the utils package. They look like teaching material rather than something that informs decisions about this codebase, and they will run on every go test -bench=. ./... invocation. Consider removing them, or moving them into a dedicated cmd/benchmarks or internal/microbench location with a clear comment about why they live in this repo.

If they stay, the _ = s lines do not actually prevent the optimizer from eliminating the loop body in future Go versions — pass s through runtime.KeepAlive or accumulate len(s) into a package-level sink to be safe.

Comment thread internal/commands/dev.go
@@ -42,56 +42,34 @@ func Dev(cmd *cobra.Command, wd string, doDelete bool, ignoreHook bool, args []s
// - If parentRepo exists OR upstream remote exists -> fork workflow
// - If no parentRepo AND no upstream remote -> single remote workflow
// Check if upstream remote exists

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: stale comment. The actual HasRemote(wd, "upstream") call was moved into LoadRepoContext, so // Check if upstream remote exists no longer corresponds to any code on the next line and is misleading when reading the function top-down. Either delete this line or rewrite it to reflect that rc.UpstreamExists is already populated by LoadRepoContext above.

Comment thread gitcmds/context.go
Comment on lines +49 to +55
for range numConcurrent {
r := <-ch
if r.err != nil {
return nil, r.err
}
r.setFn()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: first-error-wins loses information.

When the first received r.err is non-nil, the function returns immediately. The other four goroutines keep running, write to the buffered channel, and their results — including any further errors — are discarded silently. For a five-way fan-out this is probably fine in practice (and the channel is buffered to numConcurrent so there is no goroutine leak), but consider either:

  1. Draining all results and aggregating with errors.Join, so a real failure surfaces alongside any secondary failures, or
  2. Wrapping each error at the call site (e.g. fmt.Errorf("HasRemote(upstream): %w", err) inside each goroutine) so the caller can tell which sub-call actually failed.

As written, a user only ever sees one bare error message with no indication of which of the five git calls produced it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant