env

package
v1.20.1 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2023 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package env implements an Environment for ggman to run commands in.

Index

Constants

View Source
const (
	// ExitInvalidEnvironment indicates that the environment for the ggman command is setup incorrectly.
	// This typically means that the CANFILE or GGROOT is configured incorrectly, but could also indicate a different error.
	ExitInvalidEnvironment exit.ExitCode = 5

	// ExitInvalidRepo indicates that the user attempted to perform an operation on an invalid repository.
	// This typically means that the current directory is not inside GGROOT.
	ExitInvalidRepo exit.ExitCode = 6
)

Variables

View Source
var ErrEmpty = errors.New("CanLine is empty")

ErrEmpty is an error representing an empty CanLine

Functions

func Candidates added in v1.7.1

func Candidates(f Filter) []string

Candidates checks if Filter implements FilterWithCandidates and calls the Candidates() method when applicable. When Filter does not implement FilterWithCandidates, returns nil

func ComponentsOf added in v1.9.0

func ComponentsOf(s string) []string

ComponentsOf returns the components of the URL in s. It is a convenience wrapper for ParseURL(s).Components().

func FilterPredicate added in v1.12.0

func FilterPredicate(filter Filter, predicate func() bool, includeTrue bool, includeFalse bool, env Env, clonePath string) float64

FilterPredicate checks if the provided Filter matches the given predicate

Types

type CanFile

type CanFile []CanLine

CanFile represents a list of CanLines

func (*CanFile) ReadDefault

func (cf *CanFile) ReadDefault()

ReadDefault loads the default CanLines into this file.

If the default CanLines can not be read, calls panic(). A call to panic() is considered a bug.

func (*CanFile) ReadFrom

func (cf *CanFile) ReadFrom(reader io.Reader) (int64, error)

ReadFrom populates this CanFile with CanLines read from the given reader. It returns an error (if any occurred) and the total bytes read from reader.

Individual CanLines are parsed using CanLine.Unmarshal(). If reader returns a non-EOF error or parsing fails, ReadFrom returns an appropriate error.

type CanLine

type CanLine struct {
	Pattern   string
	Canonical string
}

CanLine represents a line within in the canonical configuration file

func (*CanLine) Unmarshal

func (cl *CanLine) Unmarshal(s string) error

Unmarshal reads a CanLine from a string

type DisjunctionFilter added in v1.7.1

type DisjunctionFilter struct {
	Clauses []Filter
}

DisjunctionFilter represents a filter that joins existing filters using an 'or' clause.

func (DisjunctionFilter) Candidates added in v1.7.1

func (or DisjunctionFilter) Candidates() []string

Candidates returns the candidates of this filter

func (DisjunctionFilter) Score added in v1.13.0

func (or DisjunctionFilter) Score(env Env, clonePath string) float64

Matches checks if this filter matches any of the filters that were joined. It returns the highest possible score.

type Env

type Env struct {
	// Git is a method of interacting with on-disk git repositories.
	Git git.Git

	// Vars are the values of environment variables.
	// These are used to conditionally initialize the root and CanFile values.
	Vars Variables

	// Root is the Root folder of the environment.
	// Repositories managed by ggman should be stored in this folder.
	// See the Local() method.
	Root string

	// Workdir is the working directory of this environment.
	Workdir string

	// Filter is an optional filter for the environment.
	// Repositories not matching the filter are considered to not be a part of the environment.
	// See the Repos() method.
	Filter Filter

	// CanFile is the CanFile used to canonicalize repositories.
	// See the Canonical() method.
	CanFile CanFile
}

Env represents an environment to be used by ggman.

The environment defines which git repositories are managed by ggman and where these are stored. It furthermore determines how a URL is canonicalized using a CanFile.

An environment consists of four parts, each are defined as a part of this struct. See NewEnv on the defaults used by ggman.

func NewEnv

func NewEnv(r Requirement, params Parameters) (Env, error)

NewEnv returns a new Env that fulfills the requirement r.

See methods LoadDefaultRoot() and LoadDefaultCanFile() for a description of default values.

When a CanFile is requested, it will try to load the file pointed to by the GGMAN_CANFILE environment variable. If the variable does not exist, it will attempt to load the file ".ggman" in the users HOME directory. Failing to open a CanFile, e.g. because of invalid syntax, results in an error of type Error.

If r.AllowsFilter is false, NoFilter should be passed for the filter argument. If r.AllowsFilter is true, a filter may be passed via the filter argument.

This function is untested.

func (Env) Abs

func (env Env) Abs(path string) (string, error)

Abs returns the absolute path to path, unless it is already absolute. path is resolved relative to the working directory of this environment.

func (Env) At

func (env Env) At(p string) (repo, worktree string, err error)

At returns the local path to a repository at the provided path, as well as the relative path within the repository.

The algorithm proceeds as follows:

First check if there is a repository at the provided path. If there is a repository, returns it. If there is not, recursively try parent directories until outside of the root directory.

Assumes that the root directory is set. If that is not the case, calls panic(). If no repository is found, returns an error of type Error.

func (Env) AtRoot added in v1.9.0

func (env Env) AtRoot(p string) (repo string, err error)

AtRoot checks if the path p represents the root of a repository. If p is a relative path, it will be resolved relative to the current directory.

When true it returns the absolute path to p, and no error. When false, returns the empty string and no error. When something goes wrong, returns an error.

func (Env) Canonical

func (env Env) Canonical(url URL) string

Canonical returns the canonical version of the URL url. This requires that CanFile is not nil. See the CanonicalWith() method of URL.

This function is untested.

func (*Env) LoadDefaultCANFILE

func (env *Env) LoadDefaultCANFILE() (CanFile, error)

LoadDefaultCANFILE sets and returns env.CANFILE according to the environment variables in e.Vars. If the CANFILE is already set, immediately returns nil.

If the GGMAN_CANFILE variable is set, it will use it as a filepath to read the CanFile from. If it is not set it will attempt to load the file '.ggman' in the home directory. If neither is set, this function will load an in-memory default CanFile.

If loading a CanFile fails, an error of type Error is returned. If loading succeeds, this function returns nil.

func (*Env) LoadDefaultRoot

func (env *Env) LoadDefaultRoot() error

LoadDefaultRoot sets env.Root according to the environment variables in e.Vars. If e.Root is already set, does nothing and returns nil.

If the GGROOT variable is set, it is used as the root directory. If it is not set, the subdirectory 'Projects' of the home directory is used.

The root directory does not have to exist for this function to return nil. However if both GGROOT and Home are unset, this function returns an error of type Error.

func (Env) Local

func (env Env) Local(url URL) (string, error)

Local returns the path that a repository named URL should be cloned to. Normalization of paths is controlled by the norm parameter

The error returned is either nil or of type Error.

func (Env) NewForFilter added in v1.15.0

func (env Env) NewForFilter(filter string, fuzzy bool) Filter

NewForFilter creates a new 'for' filter for this environment.

A 'for' filter may be either:

  • a (relative or absolute) path to the root of a repository (see env.AtRoot)
  • a repository url or pattern (see NewPatternFilter)

func (Env) NewFromFileFilter added in v1.15.0

func (env Env) NewFromFileFilter(p string, fuzzy bool) (filters []Filter, err error)

NewFromFileFilter creates a list of filters from the file at path.

To create a filter, p is opened and each (whitespace-trimmed) line is passed to env.NewForFilter. Blank lines, or those starting with ';', '//' or '#' are ignored.

func (Env) Normalization added in v1.12.0

func (env Env) Normalization() path.Normalization

Normalization returns the path Normalization used by this environment

func (Env) RepoScores added in v1.17.0

func (env Env) RepoScores(resolved bool) ([]string, []float64)

RepoScores returns a list of local paths to all repositories in this Environment. It also returns their scores along with the repositories. resolved indicates if their final path should be resolved

This method silently ignores all errors.

See the ScanReposScores() method for more control.

func (Env) Repos

func (env Env) Repos(resolved bool) []string

Repos returns a list of local paths to all repositories in this Environment. Resolved indicates if the final repository paths should be resolved. This method silently ignores all errors.

See the ScanRepos() method for more control.

func (Env) ResolvePathFilter added in v1.15.0

func (env Env) ResolvePathFilter(p string) (path string, err error)

ResolvePathFilter resolves and validates p for use within a PathFilter.

p must be an existing absolute absolute or relative path pointing to:

  • a repository directory (see env.At)
  • a (possibly nested) directory containing repositories

func (Env) ScanRepos

func (env Env) ScanRepos(folder string, resolved bool) ([]string, error)

ScanRepos is like ScanReposScores, but returns only the first and last return value.

func (Env) ScanReposScores added in v1.17.0

func (env Env) ScanReposScores(folder string, resolved bool) ([]string, []float64, error)

ScanRepoScores scans for repositories in the provided folder that match the Filter of this environment. Resolved indicates if the paths returned should resolve the final path of repositories. Repositories are returned in order of their scores, which are returned in the second argument.

When an error occurs, this function may still return a list of (incomplete) repositories along with an error.

type Filter

type Filter interface {
	// Score scores the repository at clonePath against this filter.
	//
	// When it does match, returns a float64 between 0 and 1 (inclusive on both ends),
	// If the filter does not match, returns -1
	Score(env Env, clonePath string) float64
}

Filter is a predicate that scores repositories inside an environment.

A filter is applied by recursively scanning the root folder for git repositories. Each folder that is a repository will be passed to clonePath.

Filter may also optionally implement FilterWithCandidates.

var NoFilter Filter = emptyFilter{}

NoFilter is a special filter that matches every directory with the highest possible score

func NewFilter

func NewFilter(flags Flags, env *Env) (filter Filter, err error)

NewFilter creates a new filter corresponding to the given Flags and Environment.

type FilterWithCandidates added in v1.7.1

type FilterWithCandidates interface {
	Filter

	// Candidates returns a list of folders that should be scanned regardless of their location.
	// A FilterWithCandidates with a Candidates() function that returns a zero-length slice is equivalent to a regular filter.
	Candidates() []string
}

FilterWithCandidates is a filter that in addition to being applied normally should also be applied to the provided candidates.

type Flags added in v1.14.0

type Flags struct {
	For           []string `` /* 214-byte string literal not displayed */
	FromFile      []string `` /* 207-byte string literal not displayed */
	NoFuzzyFilter bool     `short:"n" long:"no-fuzzy-filter" description:"disable fuzzy matching for filters"`

	Here bool     `` /* 150-byte string literal not displayed */
	Path []string `` /* 153-byte string literal not displayed */

	Dirty bool `short:"d" long:"dirty" description:"filter list of repositories to only contain repositories with uncommited changes"`
	Clean bool `short:"c" long:"clean" description:"filter list of repositories to only contain repositories without uncommited changes"`

	Synced   bool `short:"s" long:"synced" description:"filter list of repositories to only contain those which are up-to-date with remote"`
	UnSynced bool `short:"u" long:"unsynced" description:"filter list of repositories to only contain those not up-to-date with remote"`

	Tarnished bool `short:"t" long:"tarnished" description:"filter list of repositories to only contain those that are dirty or unsynced"`
	Pristine  bool `short:"p" long:"pristine" description:"filter list of repositories to only contain those that are clean and synced"`
}

Flags represents a set of filter flags used for the ggman goprogram.

type Parameters added in v1.14.0

type Parameters struct {
	Variables
	Workdir  string
	Plumbing git.Plumbing
}

Parameters represent additional parameters to create a new environment.

type PathFilter added in v1.7.1

type PathFilter struct {
	// Paths is the list of paths this filter should match with the highest possible score.
	// It is the callers responsibility to normalize paths accordingly.
	Paths []string
}

PathFilter is a filter that always matches the provided paths. It implements FilterWithCandidates.

func (PathFilter) Candidates added in v1.7.1

func (pf PathFilter) Candidates() []string

Candidates returns a list of folders that should be scanned regardless of their location.

func (PathFilter) Score added in v1.13.0

func (pf PathFilter) Score(env Env, clonePath string) float64

Score checks if a repository at clonePath matches this filter, and if so returns 1. See Filter.Score.

type PatternFilter added in v1.7.1

type PatternFilter struct {
	// contains filtered or unexported fields
}

PatternFilter is a Filter that matches both paths and URLs according to a pattern. PatternFilter implements FilterValue

func NewPatternFilter added in v1.7.1

func NewPatternFilter(value string, fuzzy bool) (pat PatternFilter)

NewPatternFilter returns a new pattern filter with the appropriate value

func (PatternFilter) MatchesURL added in v1.7.1

func (pat PatternFilter) MatchesURL(url URL) bool

MatchesURL checks if this filter matches a url

func (PatternFilter) Score added in v1.13.0

func (pat PatternFilter) Score(env Env, clonePath string) float64

Matches checks if this filter matches the repository at clonePath. The caller may assume that there is a repository at clonePath.

func (*PatternFilter) Set added in v1.7.1

func (pat *PatternFilter) Set(value string)

Set sets the value of this filter.

This function is untested because NewPatternFilter() is tested.

func (PatternFilter) String added in v1.7.1

func (pat PatternFilter) String() string

type Requirement

type Requirement struct {
	// Does the environment require a root directory?
	NeedsRoot bool

	// Does the environment allow filtering?
	// AllowsFilter implies NeedsRoot.
	AllowsFilter bool

	// Does the environment require a CanFile?
	NeedsCanFile bool
}

Requirement represents a set of requirements on the Environment.

func (Requirement) AllowsFlag added in v1.14.0

func (req Requirement) AllowsFlag(flag meta.Flag) bool

AllowsFlag checks if the provided option is allowed by this option

func (Requirement) Validate added in v1.14.0

func (req Requirement) Validate(args goprogram.Arguments[Flags]) error

type StatusFilter added in v1.12.0

type StatusFilter struct {
	Filter

	Synced, UnSynced bool
}

StatusFilter implements a CandidateFilter that filters by repositories being synced or unsynced with the remote.

func (StatusFilter) Candidates added in v1.12.0

func (sf StatusFilter) Candidates() []string

func (StatusFilter) Score added in v1.13.0

func (sf StatusFilter) Score(env Env, clonePath string) float64

type TarnishFilter added in v1.12.0

type TarnishFilter struct {
	Filter

	Tarnished, Pristine bool
}

TarnishFilter implements a CandidateFilter that filters by if they have been tarnished or not. A repository is tarnished if it has a dirty working directory, or is unsynced with the remote.

func (TarnishFilter) Candidates added in v1.12.0

func (tf TarnishFilter) Candidates() []string

func (TarnishFilter) Score added in v1.13.0

func (tf TarnishFilter) Score(env Env, clonePath string) float64

type URL

type URL struct {
	Scheme string // e.g. "ssh"

	User     string // e.g. "git"
	Password string // e.g. "p@ssw0rd"

	HostName string // e.g. "github.com"
	Port     uint16 // e.g. 2222

	Path string // e.g. "hello/world.git"
}

URL represents a URL to a single git repository.

A URL consists of different parts, and is typically created by using ParseURL.

URLs can be both concrete (that is representing a single repository) or a "pattern" matching multiple URLS. The implementation does not distinguish between either case. For pattern matching see the Match function.

func ParseURL

func ParseURL(s string) (repo URL)

ParseURL parses a URL without any namespaces. See ParseURLNamespace.

func ParseURLContext added in v1.13.0

func ParseURLContext(s string, namespaces map[string]string) (repo URL)

ParseURLContext parses a string into a repo URL, while expanding the provided namespaces.

We support two types of urls:

1. The long form: [scheme://][user[:password]@]hostname[:port]/path e.g. https://git:git@mydomain:1234/repo.git e.g. https://git@mydomain/example

2. The short form: [scheme://][user[:password]@]hostname:path e.g. mydomain:hello/world.git

A namespace may be prepended to the URL using the form 'namespace:[//]' When a namespace is encountered, the remainder of the URL is appended to the expansion of the namespace. Then the URL parsing is restarted.

Namespaces may not be nested, meaning only one expansion of namespaces is done. This is to prevent infinite loops during parsing.

ParseURLContext always succeeds. This can lead to unexpected parses of URLs when e.g. a port is specified incorrectly.

For windows compatibility, '\\' is replaced by '/' in the input string.

func (URL) Canonical

func (url URL) Canonical(cspec string) (canonical string)

Canonical returns the canonical version of this URI given a canonical specification the canonical specification can contain any character, except for three special ones ^ -- replaced by the first un-used component of the URI % -- replaced by the second un-used component of the URI (commonly username) $ -- replaced by all remaining components in the URI joined with a '/'. Also stops all processing afterwards If $ does not exist in the cspec, it is assumed to be at the end of the cspec.

func (URL) CanonicalWith

func (url URL) CanonicalWith(lines CanFile) (canonical string)

CanonicalWith returns the canonical url given a set of lines

func (URL) Components

func (url URL) Components() []string

Components gets the components of a URL

Components of the URL are the hostname, the username and components of the path. Empty components are ignored. Furthermore a username 'git' as well as a trailing suffix of '.git' are ignored as well.

func (URL) IsLocal added in v1.11.1

func (url URL) IsLocal() bool

IsLocal checks if this URL looks like a local URL. A URL is considered local if it uses the "file" scheme, or the scheme is empty and the hostname is one of ".", ".." or "".

func (*URL) UnmarshalFlag added in v1.16.0

func (u *URL) UnmarshalFlag(value string) error

type UserVariable added in v1.15.0

type UserVariable struct {
	Key         string
	Description string
	Get         func(Env, meta.Info) string
}

UserVariable is a variable that is exposed to the user. See GetUserVariables() for a details.

func GetUserVariable added in v1.15.0

func GetUserVariable(name string) (variable UserVariable, ok bool)

GetUserVariable gets a single user variable of the given name. The name is checked case-insensitive. When the variable does not exist, returns ok = False.

This function is untested because the 'ggman env' command is tested.

func GetUserVariables added in v1.15.0

func GetUserVariables() []UserVariable

GetUserVariables returns all user variables in consistent order.

This function is untested because the 'ggman env' command is tested.

type Variables

type Variables struct {
	// HOME is the path to the users' home directory
	// This is typically stored in the 'HOME' variable on unix-like systems
	HOME string

	// PATH is the value of the 'PATH' environment variable
	PATH string `env:"PATH"`

	// GGROOT is the value of the 'GGROOT' environment variable
	GGROOT string `env:"GGROOT"`

	// CANFILE is the value of the 'GGMAN_CANFILE' environment variable
	CANFILE string `env:"GGMAN_CANFILE"`

	// GGNORM is the value of the 'GGNORM' environment variable
	GGNORM string `env:"GGNORM"`
}

Variables represents the values of specific environment variables. Unset variables are represented as the empty string.

This object is used to prevent code in ggman to access the environment directly, which is difficult to test. Instead access goes through this layer of indirection which can be mocked during testing.

The env struct-tag indicates which environment variable the value corresponds to.

func ReadVariables

func ReadVariables() (v Variables)

ReadVariables reads Variables from the operating system

type WorktreeFilter added in v1.12.0

type WorktreeFilter struct {
	Filter

	// Clean and Dirty determine if clean and dirty repositories (respectively) are included
	Clean, Dirty bool
}

WorktreeFilter implements a CandidateFilter that filters by repositories having a dirty or clean working directory.

func (WorktreeFilter) Candidates added in v1.12.0

func (sf WorktreeFilter) Candidates() []string

func (WorktreeFilter) Score added in v1.13.0

func (sf WorktreeFilter) Score(env Env, clonePath string) float64

Jump to

Keyboard shortcuts

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