# Fix lint findings

`e941481`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·

golangci-lint v2.11.4 was unhappy across errcheck, exhaustive,
gocritic, inamedparam, ireturn, maintidx, noctx, perfsprint, revive,
and wrapcheck. Mostly mechanical:

\- Test helpers (initSHA1, initSHA256, mustTranslator) collapse the
'_ := ' patterns into t.Fatalf-on-error wrappers.
\- exec.Command -> exec.CommandContext(ctx, ...); ctx threaded into
runChecks and signBranchTips.
\- refs.ForEach return value checked instead of discarded.
\- if/else chain in runChecks rewritten as switch.
\- ireturn for openSource/normalizeAuth annotated, since both return
shared transport interfaces by design.
\- maintidx on Run annotated; the function is a phase orchestrator,
splitting it would obscure the pipeline.
\- exhaustive switches on plumbing.ObjectType annotated; the
unhandled cases (OFSDelta/REFDelta/AnyObject/InvalidObject) can't
reach a resolved storer.
\- Errors from io.ReadAll/MemoryObject.Reader/bufio.Flush/fmt.Fprintln/
auth.Method.Authorizer wrapped with fmt.Errorf.
\- Constant 'max' renamed to package-level 'previewMax' to stop
shadowing the builtin in two places.
\- Named parameter added to interface methods that lint flagged.
\- Two fmt.Sprintf calls replaced with string concatenation.

## Sessions

Transcript data is unavailable for this checkpoint.

## Changes

2

- cmd/git-sync/internal/sha256convert
  
  - Msha256convert.go+57/-32
  - Msha256convert_test.go+66/-25

```
131 unmodified lines

```

// previewMax caps how many items from a potentially-long list (ambiguous
// prefixes, signed tags) are inlined into a Lines() summary before
// switching to a "(N more)" suffix.
const previewMax = 5

// Lines satisfies the human-readable output contract used by other git-sync subcommands.
func (r Result) Lines() []string {
    lines := []string{
        fmt.Sprintf("sha256 bare repo: %s", r.TargetDir),
        "sha256 bare repo: " + r.TargetDir,
        fmt.Sprintf("source: %s (%s)", r.SourceURL, r.Protocol),
        fmt.Sprintf("converted: %d blobs, %d trees, %d commits, %d tags",
            r.Counts.Blobs, r.Counts.Trees, r.Counts.Commits, r.Counts.Tags),
    }
    if n := len(r.AmbiguousMessageRefs); n > 0 {
        preview := r.AmbiguousMessageRefs
        const max = 5
        extra := 0
        if len(preview) > max {
            extra = len(preview) - max
            preview = preview[:max]
        }
        if len(preview) > previewMax {
            extra = len(preview) - previewMax
            preview = preview[:previewMax]
        }
        line := fmt.Sprintf("warning: %d ambiguous SHA1 hex prefix(es) in messages left unrewritten (look up via the mapping file): %s",
            n, strings.Join(preview, ", "))

lines = append(lines, line)
    }
    if r.MappingFile != "" {
        lines = append(lines, fmt.Sprintf("mapping written to: %s", r.MappingFile))
        lines = append(lines, "mapping written to: " + r.MappingFile)
    }
    if n := len(r.SignedTags); n > 0 {
        preview := r.SignedTags
        const max = 5
        extra := 0
        if len(preview) > max {
            extra = len(preview) - max
            preview = preview[:max]
        }
        if len(preview) > previewMax {
            extra = len(preview) - previewMax
            preview = preview[:previewMax]
        }
        line := fmt.Sprintf("signed %d branch attestation tag(s): %s",
            n, strings.Join(preview, ", "))

lines = append(lines, line)
    }
    if r.TempDir != "" {
        lines = append(lines, fmt.Sprintf("kept source objects: %s", r.TempDir))
        lines = append(lines, "kept source objects: " + r.TempDir)
    }
    return lines
}

// Run performs the conversion described by req.
//nolint:maintidx // Run is a linear orchestrator over distinct phases (fetch → discover → init → translate → refs → notes → mapping → sign → check); each phase is short and isolated. Splitting into helpers would obscure the pipeline rather than clarify it.
func Run(ctx context.Context, req Request) (Result, error) {
    if req.SourceURL == "" {
        return Result{}, errors.New("convert-sha256 requires --source-url")
    }

if req.Sign {
        signed, err := signBranchTips(out, req.TargetDir, req.SignKey, req.SourceURL, desired)
        if err != nil {
            return res, fmt.Errorf("sign: %w", err)
        }
    }

if req.Check {
        fmt.Fprintln(out, "verifying output ...")
        res.Checks = runChecks(req.TargetDir, dstRepo, refsWritten)
        for _, c := range res.Checks {
            mark := "✓"
            if !c.OK {
                mark = "✗"
            }
            fmt.Fprintf(out, "%s %s
", mark, c.Name)
        }
    }
    return res, nil
}

// stdin/stderr are inherited so gpg/ssh-agent prompts work
// interactively. A failure short-circuits the run; tags signed before
// the failure stay in the target repo.
func signBranchTips(out io.Writer, targetDir, signKey, sourceURL string, desired map[plumbing.ReferenceName]planner.DesiredRef) ([]string, error) {
    gitBin, err := exec.LookPath("git")
    if err != nil {
        return nil, fmt.Errorf("git binary required to sign: %w", err)
    }

args := []string{"
    return nil
}

// Returns one Check per step. Callers print and/or fail-on-error based
// on these. No early return so users see the full picture even when an
// earlier check fails.
func runChecks(targetDir string, repo *git.Repository, refsExpected int) []Check {
    checks := []Check{}

// 1. Config: extensions.objectformat = sha256.
    // example code, unfinished.  
}

// outline of logic continues.
