Skip to content

test issue 1#148

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

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

Conversation

@host6

@host6 host6 commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

test issue 1

@augmentcode

augmentcode Bot commented Jun 10, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR refactors qs dev to pre-load repository state in fewer round-trips.

Changes:

  • Introduces gitcmds.RepoContext and gitcmds.LoadRepoContext to gather repo/org, branch info, upstream presence, and dirty state up front (with concurrent phase-1 git calls).
  • Refactors parent-repo lookup into a helper (getParentRepoByOrgRepo) and updates callers to reuse the fetched org/repo data.
  • Updates qs dev flow to rely on the new context instead of repeatedly re-running git/gh queries.
  • Handles an additional git status code (AD) in changed-file parsing to avoid treating it as an unknown status.
  • Adds a benchmark test for git ls-remote timing in the dev command area.
  • Bumps Go toolchain patch version and updates several module dependencies.
  • Minor formatting cleanup (extra whitespace in utils/semver.go).

Technical Notes: LoadRepoContext performs a second-phase GitHub API call after org/repo are known, keeping the GH call serialized but reducing total overall command latency.

🤖 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. 2 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) {
stdout, stderr, err := new(exec.PipedExec).
Command("gh", "api", "repos/"+org+slash+repo, "--jq", ".parent.full_name").

@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:485 — gh api --jq '.parent.full_name' can output the literal null when the repo isn’t a fork, so callers that use len(parentRepo)==0 may mis-detect fork vs single-remote mode. Consider normalizing this helper’s output (e.g., treat null/whitespace as empty) before returning.

Severity: medium

Fix This in Augment

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

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

@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/commands/dev_test.go:27 — out[:len(out)-1] assumes a trailing \n and can mis-trim on \r\n (and can panic if output is unexpectedly empty). Consider trimming newlines/whitespace more defensively when computing the repo root for this benchmark.

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.

Deep review of PR #148.

The main change introduces LoadRepoContext (gitcmds/context.go) which fans out five independent local-git lookups in parallel and then makes one gh api call that needs Org/Repo from phase 1. The optimization is sound: error propagation is correct (errors from any goroutine surface and the partially-populated RepoContext is discarded), and the caller in internal/commands/dev.go is refactored cleanly to use the cached values. Behavior is preserved relative to the previous serial implementation. Two ancillary changes (gitcmds/status.go adds an AD case; gitcmds/types.go adds the RepoContext struct) are coherent with that goal.

Findings:

  • 0 blockers
  • 1 medium: fragile concurrency-count constant in LoadRepoContext — silent result loss or goroutine leak if the goroutine count and numConcurrent ever drift
  • 3 low: unrelated network-dependent benchmark in dev_test.go; unsafe trailing-newline slice in the same file; narrow AD-only handling in status.go (sibling *D codes still error)
  • 1 nit: stray blank line in utils/semver.go

Verdict: safe to merge after the medium-severity concurrency comment is addressed; the rest are quality improvements.

Comment thread gitcmds/context.go
type result struct {
setFn func()
err error
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The buffered channel capacity and the receive-loop count are both hard-coded to numConcurrent = 5 and must match the number of goroutines launched below. If a future change adds a 6th goroutine without bumping this constant, the 6th send blocks forever after the loop has drained the first 5 (goroutine leak). If a goroutine is removed without decrementing it, the main goroutine blocks forever waiting for a result that never arrives (deadlock).

Consider building the work list as a []func() error (or a slice of result-producing closures) and deriving both the channel capacity and the loop bound from len(tasks) so the count cannot drift. Alternatively, use golang.org/x/sync/errgroup to manage the goroutines and propagate the first error.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

case `AD`:
    // file was added, then removed -> consider it never existed
    continue

The AD handling is correct, but the fix is narrow: other valid two-letter codes from git status --porcelain for a worktree-deleted entry — RD (renamed in index, deleted in worktree) and CD (copied in index, deleted in worktree) — still fall through to default and return unknown file status %s for file %s, which would surface as an error from Status() for users in those states.

If this scenario is reachable in practice, consider handling the worktree-deleted family generically (e.g. any XD where X is in AMRC) rather than enumerating AD only. If you intentionally want to defer those, a brief comment to that effect would help.

"github.com/stretchr/testify/require"
)

func BenchmarkGitLsRemote(b *testing.B) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Two concerns with this benchmark:

  1. It shells out to git ls-remote --heads origin main on every iteration, so it is I/O- and network-bound rather than measuring anything in this package, and will fail outright in offline environments or in any clone that does not have an origin remote with a main branch (both are realistic in CI). Consider gating with testing.Short() / explicit skip when the prerequisites are absent.
  2. The file is named dev_test.go and lives in internal/commands, but nothing here exercises Dev() or any symbol from the package. If the benchmark was kept only for ad-hoc profiling, consider removing it or relocating it to a clearly-scoped file (for example git_perf_test.go in an appropriate package).

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.

return string(out[:len(out)-1]) // trim trailing newline

If out is ever empty (len(out) == 0), this expression evaluates to out[:-1] and panics with slice bounds out of range. require.NoError only guards against a non-nil error, not against an empty-but-successful stdout. A safer, more portable form (also handles \r\n if the command ever emits CRLF):

Suggested change
}
return strings.TrimRight(string(out), "\r\n")

(remember to add "strings" to the import block).

Comment thread utils/semver.go
writeFilePermission = 0644
)


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stray empty line — no behavior change, but worth dropping to keep the file tidy.

Suggested change

@host6 host6 closed this Jun 10, 2026
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