Documentation
¶
Overview ¶
Package fork owns S27's fork orchestration. The DB row for a fork is created synchronously in Create; the on-disk `git clone --bare --shared` runs out-of-band as a `repo:fork_clone` worker job so fork creation returns fast even for large source repos.
Sync (fast-forward fork's default branch from upstream) is the other entrypoint here. Cross-fork PR support extends `internal/ pulls` and lives there; this package is just the fork lifecycle.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotLoggedIn = errors.New("fork: login required") ErrSourceNotFound = errors.New("fork: source repo not found") ErrSourceNotVisible = errors.New("fork: source repo not visible to actor") ErrTargetNameTaken = errors.New("fork: target name already exists for owner") ErrVisibilityFloor = errors.New("fork: target visibility cannot exceed source visibility") ErrSelfForkSameName = errors.New("fork: forking into the same owner requires a different name") ErrSourceArchived = errors.New("fork: source repo is archived") ErrSourceDeleted = errors.New("fork: source repo is deleted") ErrSyncDiverged = errors.New("fork: fork has diverged from upstream; sync via your client") ErrSyncUpToDate = errors.New("fork: already up to date") ErrSyncDefaultsMissing = errors.New("fork: source or fork default branch is empty") ErrSyncRefRaced = errors.New("fork: ref changed concurrently; retry") ErrForkNotInitialized = errors.New("fork: fork is still being prepared") )
Errors surfaced to handlers.
Functions ¶
This section is empty.
Types ¶
type AheadBehindStats ¶
AheadBehindStats describes how the fork's default branch relates to the source's default branch. Both numbers are commit counts: `Ahead` = commits in fork not in source; `Behind` = commits in source not in fork.
`Comparable` is false when either side's default ref doesn't exist (e.g. an empty fork before its first push, or a source that's never been initialized). The UI renders "—" in that case.
func AheadBehind ¶
AheadBehind computes the stats by reading both default OIDs, then running `rev-list --left-right --count` inside the fork's bare repo. Because forks share object alternates with their source, the fork can resolve OIDs from the source without an explicit fetch — they're already reachable through the alternates link.
This is the floor implementation. S36's perf-pass sprint adds caching keyed on `(fork_repo_id, fork_default_oid, upstream_default_oid)` so the rev-list shells out only on push (the deferral pointer is already in S36's spec).
type CreateParams ¶
type CreateParams struct {
SourceRepoID int64
ActorUserID int64
TargetOwnerID int64 // user id; org id support lands with S31
// TargetName is optional. Empty defaults to the source repo's
// name; non-empty must pass the same name validator as repo
// create (the lookup against the existing rows surfaces a
// taken-name error if needed).
TargetName string
// TargetVisibility is optional. Empty defaults to source
// visibility; non-empty must pass `allowedTargetVisibility`.
// (Public source can fork to private; private source is
// pinned to private.)
TargetVisibility string
}
CreateParams describes a fork-create request.
type CreateResult ¶
CreateResult is the inserted fork shell. The on-disk clone hasn't run yet; init_status is `init_pending`. The caller is expected to enqueue the `repo:fork_clone` worker job whose payload is {SourceRepoID, ForkRepoID}.
func Create ¶
func Create(ctx context.Context, deps Deps, p CreateParams) (CreateResult, error)
Create writes the fork's `repos` row, applies the fork_count trigger, and emits the audit row. The on-disk clone is the caller's responsibility to enqueue (the web handler does this right after Create returns).
Authorization (visibility on source, login, fork:create policy) is the caller's responsibility — this orchestrator trusts the handler's policy gate. Visibility floor + same-owner-name guards are enforced here because they're domain rules, not auth rules.
type Deps ¶
type Deps struct {
Pool *pgxpool.Pool
RepoFS *storage.RepoFS
Audit *audit.Recorder
Logger *slog.Logger
}
Deps wires this package against the rest of the runtime.
type SyncResult ¶
SyncResult describes what Sync did. Reasons cover the four outcomes the spec enumerates: fast-forwarded, already up to date, diverged (refused), or default-branch-missing (typically a freshly initialized fork or upstream that's never been pushed to).
func Sync ¶
Sync fast-forwards the fork's default branch to the upstream's. Refuses on diverged history (as the spec mandates — anything else belongs in the user's client). The CAS via UpdateRefCAS catches concurrent pushes to the fork: if a push lands between our read and our update, we return ErrSyncRefRaced and the caller can ask the user to retry.
The handler MUST authorize via policy.Can(ActionRepoWrite) on the fork before calling — Sync mutates the fork's refs and is a write action. Read access on the source is implied by ownership of the fork (you forked it; you saw it then).