The words this contract uses¶
One forge's word for a thing is another forge's word for something else, and a contract over four of them has to pick. This page records the picks and, where the choice was close, what it cost.
It exists because a term doing two jobs is the cheapest way to teach a reader the wrong model. Nothing here is a style preference; each entry is a place someone has been confused, or would be.
Repository means the forge's container, not the git repository¶
forge.Repository is the container a forge keeps a codebase in. It has a
description, a visibility, an activity timestamp and possibly a published site.
The git repository it wraps is reached through Repository.Git, a
GitRemote carrying the clone URL and default branch.
They are separable in fact rather than only in modelling. On GitLab and
Bitbucket a container can exist, carry a description and publish a site with no
git repository behind it at all — which is why GitRemote is its own type and
why its zero value is meaningful:
Everywhere else in this estate, "repo" means the git one.
gitlab.com/phpboyscout/go/repo owns cloning, branching and committing. It
exports no Repository type of its own, so there is no symbol collision, and
the package prefix carries the distinction at every call site. Inside this
package, an unqualified "repository" means the container.
Why not call it a Project¶
GitLab models this exact split and calls the container a Project, which is the better word taken alone. It is not used here because on the other three forges it collides rather than clarifies:
| Forge | What "project" means there |
|---|---|
| GitLab | The container. The meaning we would want. |
| GitHub | A planning board — ProjectV2 in the SDK this module imports. |
| Bitbucket | A grouping of repositories inside a workspace. |
| Gitea | No such concept. |
Neither of the colliding meanings is modelled here, so naming the type Project
would not create an ambiguity a caller could trip over in code. It would create
one they trip over in their own forge's UI, which is worse: the contract and the
screen in front of them would disagree about what a project is.
So the name follows the three forges that use it, and mapping GitLab's Project onto it is the provider's job rather than the caller's.
Namespace is the owner, and it is a path¶
owner in a method signature and namespace in an enumeration are the same
thing: the path segment above the repository. A user, an organisation, a GitLab
group, a Bitbucket workspace.
It is always a path string, never an ID, because a path is what a human has
and what a URL shows. Where a forge's API wants something else — GitLab's
project creation takes a numeric namespace_id — resolving it is the
provider's problem, not the caller's.
Pull request is the noun, merge request is an alias¶
PullRequests is the capability; MergeRequests is a true Go type alias for
it, so GitLab users can write the word their forge uses and get the same type.
The alias renames the type and not its methods — Go does not allow that —
so the methods carry no noun — Find, FindLastMerged, Create, Update, Close,
ResolveMergedCommit — which
is why they read differently from ReleasePublisher's. That capability spells
its methods CreateRelease and AddReleaseAsset because a provider
implementing both would otherwise need two methods called Create.
Asset means a file on a release, in one of two shapes¶
A release asset is either content the caller holds, or a location where the bytes already live. Which of the two a forge can natively hold is inverted across the family: GitLab's native asset is a link, while GitHub and Gitea take only bytes.
"Attached" means the asset is on the release. It does not mean the bytes are reachable — this contract never fetches a location to check.
Capability, provider, adapter¶
A capability is an optional interface a provider may implement, discovered
with forge.As. A provider is what a caller holds: one implementation of
forge.Provider plus whichever capabilities it satisfies. An adapter is the
module that supplies one — forge-gitlab, forge-github, forge-gitea,
forge-bitbucket, and direct which ships inside this repository.
"Provider" and "adapter" are not interchangeable. A provider is a value; an adapter is a module.
Endpoint is the address, and it is comparable¶
forge.Endpoint is where a provider talks to, as a value that compares equal
when two callers mean the same instance. That is what lets forge/pool build
each one once. It is not a URL and not a client.