Help us shape the future of Go! Take the 2026 Go Developer Survey

provider

package
v0.37.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package provider reads another repository's ebuild versions, for comparing the overlay against it and reviving packages from it. Provider is the interface; it is implemented over the GitHub and GitLab APIs, a shallow git clone kept in a cache, and a local tree read in place.

Index

Constants

View Source
const DefaultGitCloneTimeout = 5 * time.Minute

DefaultGitCloneTimeout bounds each git run the provider makes against its remote: a clone, and an update's pull, fetch and reset taken together. When it elapses, git and every process it started are stopped, and the error wraps context.DeadlineExceeded and reads "git <op> timed out after 5m0s".

Variables

View Source
var (
	// ErrRepositoryNotFound indicates the repository was not found
	ErrRepositoryNotFound = errors.New("repository not found")
	// ErrInvalidProvider indicates an invalid provider type
	ErrInvalidProvider = errors.New("invalid provider type")
)
View Source
var (
	// ErrNotFound indicates the requested resource was not found
	ErrNotFound = errors.New("package not found in repository")
	// ErrRateLimit indicates API rate limit exceeded
	ErrRateLimit = errors.New("API rate limit exceeded")
	// ErrAPIError indicates a general API error
	ErrAPIError = errors.New("API error")
	// ErrUnauthorized indicates the host rejected the credentials (HTTP 401).
	// An error carrying it also matches ErrAPIError, so callers that only
	// know about ErrAPIError keep treating a 401 as one.
	ErrUnauthorized = errors.New("authentication rejected")
	// ErrCloneFailed indicates git clone operation failed
	ErrCloneFailed = errors.New("git clone failed")
	// ErrInvalidRepoURL indicates the repository URL has a scheme outside the
	// allowed set {http, https, git, ssh}, or an empty host.
	ErrInvalidRepoURL = errors.New("invalid repository URL")
	// ErrInvalidBranch indicates the git branch name fails git check-ref-format
	// style validation (control chars, "..", "@{", a leading "-", shell
	// metacharacters, and similar unsafe constructs).
	ErrInvalidBranch = errors.New("invalid git branch name")
)

Functions

func ListAvailableRepositories

func ListAvailableRepositories(ctx context.Context, configRepos map[string]*RepositoryInfo, registry *RepositoryRegistry) []string

ListAvailableRepositories returns a sorted list of all available repository names from both config and registry sources, deduplicated.

func ValidateBranch

func ValidateBranch(b string) error

ValidateBranch validates a git branch name against a conservative subset of "git check-ref-format". It rejects b when it:

  • is empty,
  • contains whitespace,
  • contains an ASCII control character,
  • contains the ".." sequence,
  • contains the "@{" sequence,
  • has a leading "-" (which enables git flag-injection),
  • contains any of the metacharacters ~ ^ : ? * [ \,
  • contains a Unicode right-to-left override (U+202E),
  • contains a NUL byte,
  • starts with "/", ends with "/", or contains "//" (empty path component),
  • ends with ".",
  • is exactly "@", or
  • has a "/"-separated component that starts with "." or ends with ".lock".

On failure it returns an error wrapping ErrInvalidBranch. The rule set is intentionally never more permissive than git: any branch this function accepts also passes "git check-ref-format --branch".

func ValidateRepoURL

func ValidateRepoURL(raw string) error

ValidateRepoURL parses raw with net/url and rejects any repository URL whose scheme is outside the allowed set {http, https, git, ssh} or whose host is empty. The scheme comparison is case-insensitive.

A URL whose trimmed form begins with "-" is rejected outright (before any parsing): git would otherwise treat such a positional argument as an option, enabling flag-injection (e.g. "--upload-pack=...").

The scp-like SSH shorthand "user@host:path" (which net/url cannot parse) is treated as a valid SSH remote: it has no scheme and no shell metacharacters of concern here, and the design explicitly allows the "ssh" transport.

On failure it returns an error wrapping ErrInvalidRepoURL.

Types

type CacheEntry

type CacheEntry struct {
	Versions  []string  `json:"versions"`
	Timestamp time.Time `json:"timestamp"`
}

CacheEntry represents a cached API response

type ContentEntry

type ContentEntry struct {
	Name        string `json:"name"`
	Path        string `json:"path"`
	Type        string `json:"type"` // "file" or "dir"
	DownloadURL string `json:"download_url,omitempty"`
}

ContentEntry represents a file/directory entry from GitHub Contents API

type GitCloneProvider

type GitCloneProvider struct {
	RepoURL   string
	LocalPath string
	Branch    string
	RepoName  string

	// UpdateInterval is how often to pull updates (default: 24h)
	UpdateInterval time.Duration
	// contains filtered or unexported fields
}

GitCloneProvider fetches package versions by cloning a git repository

func NewGitCloneProvider

func NewGitCloneProvider(repoInfo *RepositoryInfo) (*GitCloneProvider, error)

NewGitCloneProvider creates a new git clone provider.

The resolved repository URL and branch name are validated before any work is done: a malicious scheme (e.g. file://, javascript:) or a branch name that enables git flag-injection causes an early error wrapping ErrInvalidRepoURL or ErrInvalidBranch respectively.

func NewLocalProvider

func NewLocalProvider(repoInfo *RepositoryInfo) (*GitCloneProvider, error)

NewLocalProvider builds a provider that reads an on-disk package tree in place (provider "local"), without cloning. repoInfo.Path must be an existing directory; it is resolved to an absolute path and used as LocalPath directly. This is the "local tree" the revive/compare guidance documents — e.g. a synced /var/db/repos/gentoo, which has no .git of its own.

func (*GitCloneProvider) Close

func (p *GitCloneProvider) Close() error

Close cleans up resources (nothing to clean for git clone)

func (*GitCloneProvider) ForceUpdate

func (p *GitCloneProvider) ForceUpdate() error

ForceUpdate forces an update of the repository regardless of age. It is a no-op for a local in-place tree, which bentoo does not own and must not pull.

func (*GitCloneProvider) GetName

func (p *GitCloneProvider) GetName() string

GetName returns the provider name

func (*GitCloneProvider) GetPackageVersions

func (p *GitCloneProvider) GetPackageVersions(ctx context.Context, category, pkg string) ([]string, error)

GetPackageVersions returns all ebuild versions for a package. A ctx that is already done returns its error before the repository is touched.

func (*GitCloneProvider) LocalPackagePath

func (p *GitCloneProvider) LocalPackagePath(category, pkg string) (string, error)

LocalPackagePath returns the on-disk directory for a package in the cloned repository, ensuring the repo is present/up-to-date first. It returns ErrNotFound if the package directory does not exist.

func (*GitCloneProvider) RemoveCache

func (p *GitCloneProvider) RemoveCache() error

RemoveCache removes the cached repository. It is a no-op for a local in-place tree: LocalPath there is the user's real tree (e.g. /var/db/repos/gentoo), not a bentoo-managed cache, so os.RemoveAll must never run against it.

func (*GitCloneProvider) SetReporter

func (p *GitCloneProvider) SetReporter(r tui.Reporter, id string)

SetReporter wires a reporter and task id for clone stage/done/tail events. A nil reporter is normalized to tui.Noop().

func (*GitCloneProvider) SupportsAPI

func (p *GitCloneProvider) SupportsAPI() bool

SupportsAPI returns false - this provider uses git clone, not API

type GitHubProvider

type GitHubProvider struct {
	BaseURL    string
	Repository string // e.g., "gentoo/gentoo"
	UserAgent  string
	Token      string
	HTTPClient *http.Client
	CacheDir   string
	CacheTTL   time.Duration
}

GitHubProvider fetches package versions from GitHub API

func NewGitHubProvider

func NewGitHubProvider(repoInfo *RepositoryInfo) (*GitHubProvider, error)

NewGitHubProvider creates a new GitHub API provider

func (*GitHubProvider) Close

func (p *GitHubProvider) Close() error

Close cleans up resources

func (*GitHubProvider) GetName

func (p *GitHubProvider) GetName() string

GetName returns the provider name

func (*GitHubProvider) GetPackageVersions

func (p *GitHubProvider) GetPackageVersions(ctx context.Context, category, pkg string) ([]string, error)

GetPackageVersions fetches all ebuild versions for a package from GitHub

func (*GitHubProvider) GetRateLimitInfo

func (p *GitHubProvider) GetRateLimitInfo(ctx context.Context) (remaining int, resetTime time.Time, err error)

GetRateLimitInfo returns current rate limit status. The request is bound to ctx: cancelling it aborts the lookup in flight, and the returned error wraps ctx.Err().

func (*GitHubProvider) SetCacheDir

func (p *GitHubProvider) SetCacheDir(dir string) error

SetCacheDir sets the cache directory for API responses

func (*GitHubProvider) SupportsAPI

func (p *GitHubProvider) SupportsAPI() bool

SupportsAPI returns true

type GitLabProvider

type GitLabProvider struct {
	BaseURL    string // e.g., "https://gitlab.com" or "https://gitlab.gentoo.org"
	ProjectID  string // URL-encoded project path or numeric ID
	Token      string
	UserAgent  string
	HTTPClient *http.Client
	CacheDir   string
	CacheTTL   time.Duration
}

GitLabProvider fetches package versions from GitLab API

func NewGitLabProvider

func NewGitLabProvider(repoInfo *RepositoryInfo) (*GitLabProvider, error)

NewGitLabProvider creates a new GitLab API provider

func (*GitLabProvider) Close

func (p *GitLabProvider) Close() error

Close cleans up resources

func (*GitLabProvider) GetName

func (p *GitLabProvider) GetName() string

GetName returns the provider name

func (*GitLabProvider) GetPackageVersions

func (p *GitLabProvider) GetPackageVersions(ctx context.Context, category, pkg string) ([]string, error)

GetPackageVersions fetches all ebuild versions for a package from GitLab

func (*GitLabProvider) SupportsAPI

func (p *GitLabProvider) SupportsAPI() bool

SupportsAPI returns true

type GitLabTreeEntry

type GitLabTreeEntry struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Type string `json:"type"` // "blob" or "tree"
	Path string `json:"path"`
	Mode string `json:"mode"`
}

GitLabTreeEntry represents a file/directory entry from GitLab Repository Tree API

type PackageDirProvider

type PackageDirProvider interface {
	LocalPackagePath(category, pkg string) (string, error)
}

PackageDirProvider is implemented by providers that expose an on-disk package directory (git clone / local tree). The revive flow type-asserts to it (autoupdate.CanRevive); an API-only provider simply does not implement it, which is the "API-only" signal.

type Provider

type Provider interface {
	// GetPackageVersions returns all ebuild versions for a package. ctx ends
	// the lookup: an HTTP implementation sends its request with it.
	GetPackageVersions(ctx context.Context, category, pkg string) ([]string, error)

	// GetName returns a human-readable name for this provider
	GetName() string

	// SupportsAPI returns true if this provider uses an API (vs git clone)
	SupportsAPI() bool

	// Close cleans up any resources (e.g., temporary directories)
	Close() error
}

Provider is the interface for fetching package versions from a repository

func NewProvider

func NewProvider(repoInfo *RepositoryInfo, forceClone bool) (Provider, error)

NewProvider creates a new Provider based on the repository info If forceClone is true, always use git clone instead of API

type RepositoryInfo

type RepositoryInfo struct {
	Name     string // e.g., "gentoo", "guru", "my-overlay"
	Provider string // "github", "gitlab", "git", "local"
	URL      string // Full URL or org/repo for GitHub/GitLab/git (remote)
	Path     string // On-disk tree for provider "local" (read in place, no clone)
	Token    string // Optional auth token
	Branch   string // Branch to use (default: master/main)
}

RepositoryInfo contains information about a repository to compare against

func ResolveRepository

func ResolveRepository(ctx context.Context, name string, configRepos map[string]*RepositoryInfo, registry *RepositoryRegistry) (*RepositoryInfo, error)

ResolveRepository resolves a repository name to its full info. Priority: config repos > registry > error.

func (*RepositoryInfo) Clone

func (r *RepositoryInfo) Clone() *RepositoryInfo

Clone returns a copy of the RepositoryInfo

type RepositoryRegistry

type RepositoryRegistry struct {
	CacheDir string
	CacheTTL time.Duration
	XMLPath  string
	// contains filtered or unexported fields
}

RepositoryRegistry fetches, caches, and parses repositories.xml

func NewRepositoryRegistry

func NewRepositoryRegistry() (*RepositoryRegistry, error)

func (*RepositoryRegistry) List

func (r *RepositoryRegistry) List(ctx context.Context) ([]string, error)

List returns every repository name in the registry, sorted; a download it needs is cancellable through ctx.

func (*RepositoryRegistry) Resolve

func (r *RepositoryRegistry) Resolve(ctx context.Context, name string) (*RepositoryInfo, error)

Resolve looks name up in the registry; a download it needs is cancellable through ctx.

func (*RepositoryRegistry) Sync

func (r *RepositoryRegistry) Sync(ctx context.Context) error

Sync forces a download of the registry, cancellable through ctx.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL