Documentation
¶
Overview ¶
Package gitconfig reads and edits git configuration files exactly like git does: same parsing, same value semantics, same scopes and includes, and edits that change only the lines they touch.
The API has three parts:
- Config is an immutable set of entries, for reading.
- File is the lossless, editable form of a single file.
- Env says where git's configuration comes from, and is the only way to the disk: it loads scopes or files (following includes) and edits them with git's lock file protocol, so that git and this package can safely write the same file.
Reading the effective configuration of a repository and changing a value:
env, err := gitconfig.Discover(".") // the working tree
if err != nil { ... } // ErrNotRepository, or ErrUntrusted
cfg, err := env.Load()
if err != nil { ... }
if e, ok := cfg.Get("user.name"); ok {
fmt.Println(e.Value)
}
err = env.UpdateScope(gitconfig.ScopeLocal, func(f *gitconfig.File) error {
return f.Set("core.editor", "vim")
})
Nothing in this package reads the process environment or the home directory, except Discover, and only Discover and the methods of Env touch the filesystem. An Env built by hand is fully described by its fields. Parse, File and Config do no I/O, for callers that store configuration their own way.
Errors wrap the sentinel errors of this package (ErrLocked, ErrInvalidKey, ...) in a typed error giving the key, file or value concerned; the documentation of the error variables says which function returns which type.
Index ¶
- Variables
- type CommandEntry
- type Config
- func (c *Config) All() iter.Seq[Entry]
- func (c *Config) Bool(key string, def bool) (bool, error)
- func (c *Config) Get(key string) (Entry, bool)
- func (c *Config) GetAll(key string) []Entry
- func (c *Config) Int(key string, def int64) (int64, error)
- func (c *Config) Path(key, home, def string) (string, error)
- func (c *Config) Section(section string) iter.Seq[Entry]
- func (c *Config) Subsection(section, sub string) iter.Seq[Entry]
- func (c *Config) Subsections(section string) []string
- func (c *Config) Value(key string, def string) string
- type Entry
- type Env
- func (e Env) Load() (*Config, error)
- func (e Env) LoadFile(path string) (*Config, error)
- func (e Env) LoadProtected() (*Config, error)
- func (e Env) LoadScope(s Scope) (*Config, error)
- func (e Env) UpdateFile(path string, fn func(*File) error) error
- func (e Env) UpdateScope(s Scope, fn func(*File) error) error
- func (e Env) WritePath(s Scope) (string, error)
- type EnvError
- type File
- func (f *File) Add(key, value string) error
- func (f *File) Bytes() []byte
- func (f *File) Config() *Config
- func (f *File) RemoveSection(section string) (removed bool, err error)
- func (f *File) RemoveSubsection(section, sub string) (removed bool, err error)
- func (f *File) RenameSection(oldName, newName string) error
- func (f *File) RenameSubsection(section, oldSub, newSub string) error
- func (f *File) ReplaceAll(key, value string) error
- func (f *File) Set(key, value string) error
- func (f *File) Unset(key string) (removed bool, err error)
- func (f *File) UnsetAll(key string) (removed int, err error)
- type FileError
- type Key
- type KeyError
- type Origin
- type Scope
- type SyntaxError
- type ValueError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound is returned when the section or subsection to rename is // absent. Removing something absent is not an error. ErrNotFound = errors.New("gitconfig: not found") // ErrMultipleValues is returned when a single-value operation finds // several values. ErrMultipleValues = errors.New("gitconfig: multiple values") // ErrInvalidKey is returned when an edit, ParseKey or a CommandEntry is // given a key or section name that git rejects. Reads treat such a key // as absent. ErrInvalidKey = errors.New("gitconfig: invalid key") // ErrInvalidValue is returned when an edit is given a value git cannot // store: one that contains a NUL byte. ErrInvalidValue = errors.New("gitconfig: invalid value") // ErrLocked is returned when the lock file exists: another process is // writing. ErrLocked = errors.New("gitconfig: config file is locked") // ErrIncludeDepth is returned when includes nest more than 10 levels, // usually because of a cycle. ErrIncludeDepth = errors.New("gitconfig: exceeded maximum include depth") // ErrLoadLimit is returned when one load would read more than 1000 // files, 4 MiB, or 2¹⁶ entries and distinct section headers in total // from files (entries of Env.Command are not counted). // Parse applies the byte and entry limits to its one file, and keeps at // most 2¹⁸ pieces of it (blank lines, comments, ...); an edit that would // take a File beyond these limits fails with it. ErrLoadLimit = errors.New("gitconfig: exceeded load limits") // ErrNotRegular is returned when a configuration file or an include is // not a regular file (a directory, a FIFO, a device). ErrNotRegular = errors.New("gitconfig: not a regular file") // ErrNotAbsolute is returned when Env.GitDir, or an include.path given // on the command line, is a relative path. ErrNotAbsolute = errors.New("gitconfig: path is not absolute") // ErrNoScope is returned when a scope does not exist or cannot be written // in an Env. ErrNoScope = errors.New("gitconfig: scope not available") // ErrUntrusted is returned by Discover for a repository git would // refuse: not owned by the current user, and not listed in // safe.directory. The *FileError's Path is the path to list. ErrUntrusted = errors.New("gitconfig: repository not owned by the current user nor listed in safe.directory") // ErrNotRepository is returned by Discover for a directory that is not // a repository: the git directory expected, its .git when it exists and // the directory itself otherwise, holds no HEAD file, or its common // directory no objects and refs directories. The *FileError's Path is // that git directory. ErrNotRepository = errors.New("gitconfig: not a git repository") // ErrClosed is returned when a File is edited after the callback of // Env.UpdateFile or Env.UpdateScope has returned. ErrClosed = errors.New("gitconfig: file is closed") )
The sentinel errors below are returned wrapped in a typed error that says which key, file or value is concerned; test them with errors.Is, and get the context with errors.As:
- ParseKey and File edits return a *KeyError.
- Parse returns a *SyntaxError, or a *FileError for load limits.
- Typed reads (Config.Bool, Entry.Int, ...) return a *ValueError.
- Env methods and Discover return a *FileError for anything about a file (reading, a *SyntaxError, includes, load limits, locking, writing), a *KeyError for an invalid CommandEntry key, and ErrNoScope unwrapped, as no file is concerned. The error returned by the callback of Env.UpdateFile or Env.UpdateScope is returned as is.
- Discover also returns an *EnvError for an environment variable it cannot interpret, ErrNotRepository in a *FileError for a directory that is not a repository, and ErrUntrusted in a *FileError for a repository git would refuse.
Error messages name files, whose paths can come from a configuration file someone else wrote. As in git, but stricter, control characters (newline and tab included), bidirectional controls and bytes that are not UTF-8 are replaced with '?', so that a path cannot drive the terminal it is printed to, nor forge a line or disguise itself. The fields of the errors, and Entry, Origin and Key, hold the raw data: quote them before printing them yourself.
Functions ¶
This section is empty.
Types ¶
type CommandEntry ¶
type CommandEntry struct {
Key string
Value string
Implicit bool // "git -c key" without "=": true as a boolean
}
CommandEntry is one value given on the command line. Key is validated by Load: a key git rejects makes Load fail with ErrInvalidKey, as git does. An include.path given this way is followed; a relative one is ErrNotAbsolute, as git refuses relative includes that do not come from a file.
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config is an immutable, ordered set of entries, from a single file or from several scopes. It is safe for concurrent use. A nil *Config is empty.
Keys are given as in `git config`: "section.name" or "section.subsection.name". Section and name are case-insensitive, the subsection is case-sensitive; a legacy header [a.B] holds subsection "b", as git lowers it. An invalid key is never present: every read treats it as absent. Keys are usually constants in the caller's code; check them once with ParseKey, for example in a test.
When a key has several values, the last one wins, as in git: Get, Value, Bool, Int and Path use it, GetAll returns them all.
func (*Config) Bool ¶
Bool returns the last value for key as a boolean, or def if key is absent. A value that is not a valid boolean is a *ValueError; the result is then def. To tell an absent key from one set to def, use Get and Entry.Bool.
func (*Config) GetAll ¶
GetAll returns every entry for key, in order. The returned slice is owned by the caller.
func (*Config) Int ¶
Int returns the last value for key as an integer, or def if key is absent. A value that is not a valid integer is a *ValueError; the result is then def.
func (*Config) Path ¶
Path returns the last value for key expanded as a path by Entry.Path, or def if key is absent, expanded the same way. home is the home directory, usually Env.Home.
A value that cannot be expanded is a *ValueError, and the result is then def, unexpanded. This also holds for def itself: its error reports it with an empty Origin, and a zero Key if key is invalid.
func (*Config) Section ¶
Section returns every entry of section [section] itself, in order; entries of its subsections are not included. section is case-insensitive.
func (*Config) Subsection ¶
Subsection returns every entry of subsection [section "sub"], in order. section is case-insensitive, sub is case-sensitive. sub "" is the empty subsection [section ""], distinct from [section].
func (*Config) Subsections ¶
Subsections returns the distinct subsections of section, in order of first appearance. For example Subsections("remote") lists the remote names. Entries of [section] itself have no subsection and are not listed; "" stands for [section ""].
type Entry ¶
type Entry struct {
Key Key
// Value is the decoded value: quotes removed, escapes resolved,
// continuation lines joined, unquoted leading and trailing whitespace
// trimmed.
Value string
// Implicit is true for a key written without '=' ("[a]\n\tk"). Value is
// then "", and the entry reads as true as a boolean.
Implicit bool
Origin Origin
}
Entry is one occurrence of a key in a configuration file. It is plain data: two entries with the same fields are equal.
func (Entry) Bool ¶
Bool interprets the value as git does: true, yes, on and non-zero integers are true; false, no, off, 0 and "" are false; an implicit value is true. Case is ignored. Anything else is a *ValueError.
func (Entry) Int ¶
Int interprets the value as git does: a decimal number, or octal with a leading "0" and hexadecimal with a leading "0x" as in C (so "010" is 8), optionally followed by a unit k, m or g (×1024, ×1024², ×1024³), case ignored. An invalid number or unit, a value out of the int64 range or an implicit value is a *ValueError.
func (Entry) Path ¶
Path interprets the value as a path, as git does for `--type=path` and for include paths: a leading "~/", or a value of "~" alone, is replaced by home, usually Env.Home. Other values are returned unchanged; relative paths are not resolved.
These are a *ValueError: "~" or "~/" with an empty home, "~user/" (not supported), a leading "%(prefix)/" (the install prefix of the git binary, unknown to this package) and an implicit value.
type Env ¶
type Env struct {
// Home is the user's home directory. Load uses it to expand "~/" in
// include paths; pass it to Config.Path and Entry.Path for values.
// "" makes such paths an error.
Home string
// GitDir is the repository's git directory, "" outside a repository.
// It must be absolute: includeIf "gitdir:" matches absolute paths, and
// a relative GitDir makes Load fail with ErrNotAbsolute rather than
// silently not match. For a linked worktree, this is the worktree's
// own git directory (.git/worktrees/<name>): the shared config is found
// through its commondir file, and config.worktree is read from it.
// includeIf "onbranch:" reads <GitDir>/HEAD when such a condition is
// met.
GitDir string
// SystemConfig is the system configuration file, "" for none.
SystemConfig string
// GlobalConfig lists the global configuration files, read in order.
// Writes go to the last one that exists, or to the last one if none
// exists: for git's [XDG file, ~/.gitconfig] this picks ~/.gitconfig
// unless only the XDG file exists. A symbolic link exists if its target
// does.
GlobalConfig []string
// Command holds the values given on the command line (git -c,
// GIT_CONFIG_COUNT, GIT_CONFIG_PARAMETERS), in order.
Command []CommandEntry
}
Env says where git's configuration comes from: the system file, the global files, the repository and the command line. Discover fills it as git does; tests and embedders can fill it by hand. Every field is used as given, and a zero source field means "none": an Env reads nothing it was not given. An Env is a value, but copies share the GlobalConfig and Command slices: replace them rather than modify them in place.
Configuration can come from someone else: a repository on a shared disk, an unpacked archive, a file reached through include.path. Loading such a file is safe (bounded, see Load), but its values are not to be trusted. Discover refuses a repository git would refuse (ErrUntrusted); an Env filled by hand is not checked, as git does not check a repository named by GIT_DIR.
func Discover ¶
Discover finds where git's configuration comes from, the way git does, using the running process: environment variables (GIT_CONFIG_GLOBAL, XDG_CONFIG_HOME, …), the user's home directory, the working directory and the platform's system configuration file.
dir is where the repository is found, as git finds it when started there (git -C dir): a working tree (a directory holding .git), its .git, or a git directory, such as a bare repository; it is made absolute. A .git file holding "gitdir: <path>", as in a linked worktree or a submodule, is followed. Finding the repository is left to the caller: Discover does not search parent directories and does not read GIT_DIR. Pass "" when not in a repository: only the system, global and command-line scopes exist then. A dir that is not a repository fails with ErrNotRepository, in a *FileError naming the git directory expected: its .git when it exists (or the directory a gitdir file names), dir itself otherwise. As for git, a git directory must hold a HEAD file, and its common directory objects and refs directories; any other would have its config read and written as the local scope. A caller that wants the repository only when there is one can fall back to Discover("") on ErrNotRepository.
The repository must be trusted, as git requires: owned by the current user (on Unix, also the SUDO_UID user for root; on Windows, the Administrators group for an administrator), or listed in safe.directory. Otherwise Discover fails with ErrUntrusted, in a *FileError naming the path to list. As in git, that path is the working tree when dir is one, dir itself otherwise: pass the working tree when there is one.
Without a home directory, Home is "" and the global files are those git reads then: the XDG file if XDG_CONFIG_HOME is set, no ~/.gitconfig.
On Windows, SystemConfig is "" unless GIT_CONFIG_SYSTEM is set: the system file lives in git's installation directory, which Discover does not look for. Set the field to read it.
It fails if a gitdir file is malformed (a *FileError), or if GIT_CONFIG_NOSYSTEM, GIT_CONFIG_COUNT or GIT_CONFIG_PARAMETERS is malformed (an *EnvError), as git does.
It is the only function of this package that reads the process environment.
func (Env) Load ¶
Load returns the effective configuration: system, global, local, worktree and command-line scopes, in that order of precedence, with includes followed. This is what git itself uses. Each entry's Origin.Scope tells which scope it comes from. Missing files are skipped.
Includes are followed as git does (include.path and includeIf with the gitdir:, gitdir/i: and onbranch: conditions; hasconfig: is never true), up to 10 levels deep (ErrIncludeDepth). Two safety bounds git lacks are added: an include must be a regular file (ErrNotRegular, so a FIFO or a device cannot hang or exhaust the process), and one load reads at most 1000 files, 4 MiB and 2¹⁶ entries and distinct section headers in total from files (ErrLoadLimit, so that a file including itself many times cannot multiply the work exponentially, and a file of tiny entries cannot exhaust memory). Real configurations never come near these bounds.
As in git, includes are followed as a file is read: an error in an included file is reported before a syntax error further down the file that includes it.
A global file that cannot be read for lack of permission is skipped, as git does; LoadProtected skips such a system file too.
Example ¶
Read the effective configuration of a repository, as git would use it.
package main
import (
"fmt"
"log"
"github.com/git-bug/gitconfig"
)
func main() {
env, err := gitconfig.Discover(".")
if err != nil {
log.Fatal(err)
}
cfg, err := env.Load()
if err != nil {
log.Fatal(err)
}
if e, ok := cfg.Get("user.name"); ok {
fmt.Println("user:", e.Value)
}
bare, err := cfg.Bool("core.bare", false)
if err != nil {
log.Fatal(err)
}
fmt.Println("bare:", bare)
}
Output:
func (Env) LoadFile ¶
LoadFile returns the configuration of the file at path, with includes followed, like `git config --includes -f <path>` (git itself follows includes there only with --includes). Its entries have ScopeFile. A missing file is empty.
func (Env) LoadProtected ¶
LoadProtected returns the configuration of the protected scopes only, with includes followed: system, global and command line, in that order. This is what git uses for keys a repository must not be able to set, such as safe.directory or safe.bareRepository. The repository's configuration is not read.
func (Env) LoadScope ¶
LoadScope returns the configuration of exactly one scope, with includes followed, like `git config --includes --<scope>` (git itself follows includes there only with --includes). Lower scopes are not included.
ScopeGlobal is the whole global layer, every file of GlobalConfig, as in Load. `git config --global` differs: it reads only the file it writes to (WritePath), so keys of the XDG file are not listed while ~/.gitconfig exists.
A scope with no file (SystemConfig "", a global or worktree file that does not exist) is empty, as for `git config --get`. ScopeWorktree reads the file WritePath gives: without extensions.worktreeConfig, that is the repository's config, and its entries have ScopeLocal, as git reports. It fails with ErrNoScope for ScopeFile, and for ScopeLocal and ScopeWorktree where WritePath does.
func (Env) UpdateFile ¶
UpdateFile edits the file at path with git's lock protocol, like `git config -f <path>`:
- if path is a symbolic link, follow it (up to 5 levels, relative targets resolved against the link's directory) and edit the target: the link itself is kept;
- create <target>.lock exclusively, never through a symbolic link, or fail with ErrLocked immediately, as git does;
- read and parse the target under the lock (a missing file is empty), into a File;
- call fn, exactly once;
- if the content changed, write it to the lock file, give it the target's permission bits exactly (chmod, so the umask does not apply; a new file gets 0666 minus the umask), and rename it over the target; otherwise leave the target alone.
On Windows, opening or replacing the target is retried for up to a second while another process holds it, as a concurrent writer or a reader does for a moment.
If fn returns an error or panics, the lock is released and nothing is written; the panic then continues. Readers see either the old or the new file, never a partial one. After fn returns, edits of the File fail with ErrClosed.
Following the symbolic link in step 1 is what git does, and what dotfile managers rely on. It also means that whoever controls the directory of path controls which file is written: do not edit the configuration of a repository that Discover has not accepted.
func (Env) UpdateScope ¶
UpdateScope edits the file of scope s, which WritePath gives, as UpdateFile does; it fails with ErrNoScope where WritePath does. The File's entries have the scope LoadScope gives them. Writes never go into an included file.
Example ¶
Change a value in the repository's config. Comments and layout are kept, and the file is not touched if the value is already set.
package main
import (
"log"
"github.com/git-bug/gitconfig"
)
func main() {
env, err := gitconfig.Discover(".")
if err != nil {
log.Fatal(err)
}
err = env.UpdateScope(gitconfig.ScopeLocal, func(f *gitconfig.File) error {
return f.Set("core.editor", "vim")
})
if err != nil {
log.Fatal(err)
}
}
Output:
func (Env) WritePath ¶
WritePath returns the file that `git config --<scope>` writes to. For ScopeWorktree, that is config.worktree if extensions.worktreeConfig is set, otherwise the repository's config as for ScopeLocal, provided the repository has a single worktree. It fails with ErrNoScope if the scope cannot be written in this Env: ScopeFile and ScopeCommand always, ScopeSystem with no SystemConfig, ScopeGlobal with no GlobalConfig, ScopeLocal and ScopeWorktree outside a repository, ScopeWorktree in a repository with several worktrees and no extensions.worktreeConfig.
type EnvError ¶
type EnvError struct {
Var string // the variable's name, e.g. "GIT_CONFIG_COUNT"
Err error // the reason
}
EnvError reports an environment variable Discover cannot interpret, as git refuses it: a malformed GIT_CONFIG_NOSYSTEM, GIT_CONFIG_COUNT or GIT_CONFIG_PARAMETERS, or a missing GIT_CONFIG_KEY_<n> or GIT_CONFIG_VALUE_<n>.
type File ¶
type File struct {
// contains filtered or unexported fields
}
File is the lossless, editable form of one configuration file. Edits change only the lines `git config` would change, and produce the same bytes; everything else (comments, blank lines, indentation) is kept byte for byte.
A File comes from Parse, for content that is not on disk (tests, in-memory repositories, a .gitmodules blob), or from Env.UpdateScope and Env.UpdateFile, to edit a file on disk. The zero value is an empty file.
A File is mutable and must not be used by several goroutines at once. Use Config to take an immutable snapshot; its entries have the scope the File was opened for by Env.UpdateScope, and ScopeFile otherwise.
Edits find keys, sections and subsections as Config does: section and name case-insensitive, subsection exact, a legacy header [a.B] holding subsection "b". git differs in two places: it places a key with an upper-case subsection into a matching legacy header, where it reads back lowered, and it removes or renames a section only if the header is spelled as given.
A new key goes at the end of the last section that holds its section or subsection, or into a new section at the end of the file, as git does.
Edits return a *KeyError wrapping ErrInvalidKey if a key or section name is one git rejects, or a key has an empty section (".sub.name", which git reads from a header [ "sub"]), and wrapping ErrInvalidValue if a value contains a NUL byte. An edit that would take the file beyond the limits of Parse is a *KeyError wrapping ErrLoadLimit. Removing something that is absent is not an error: the methods report what they removed.
An edit cannot inject anything: whatever the key, subsection and value, the edited file parses to the entries before the edit with exactly that one change. Values are quoted and escaped as git does, and a subsection that cannot be written in a header (newline, NUL) is ErrInvalidKey.
func Parse ¶
Parse parses a configuration file. name is used in errors and in the Origin of entries, which have ScopeFile. A file git rejects is a *SyntaxError. An entry before any section header, which git reads under a key no command can ask for, is kept in the file but is not an entry of Config.
data may come from anyone (a .gitmodules blob from a remote): Parse never panics, and its time and memory are linear in len(data). It applies the limits of a load to its one file: more than 4 MiB, more than 2¹⁶ entries and distinct section headers, or more than 2¹⁸ pieces (blank lines, comments, ...) is a *FileError wrapping ErrLoadLimit.
func (*File) Add ¶
Add adds a value to key, keeping existing ones, like `git config --add`. The new value is read last, so it is the one Config.Get returns.
func (*File) Bytes ¶
Bytes returns the content of the file. It is identical to the parsed data if the file was not edited.
func (*File) Config ¶
Config returns an immutable snapshot of the entries of this file. Include directives are not followed; use Env to load configuration with includes.
After the callback of Env.UpdateFile returns, Bytes and Config still give the last content, but edits fail with ErrClosed.
The snapshot is kept until the next edit, so calling Config repeatedly, for example to read values inside an Env.UpdateFile callback, is cheap.
func (*File) RemoveSection ¶
RemoveSection removes section [section] and all its entries, like `git config --remove-section <section>`, and reports whether it was present. Its subsections are kept.
func (*File) RemoveSubsection ¶
RemoveSubsection removes subsection [section "sub"] and all its entries, like `git config --remove-section <section>.<sub>`, and reports whether it was present. sub "" is the empty subsection [section ""].
func (*File) RenameSection ¶
RenameSection renames section [oldName] to [newName], like `git config --rename-section`. Subsections are not renamed. It fails with ErrNotFound if the section is absent.
Only the headers change, and whether [newName] exists is not checked: if it does, both sections remain and read as one, as with git. To refuse instead, check f.Config() first, in the same Env.UpdateFile callback.
func (*File) RenameSubsection ¶
RenameSubsection renames subsection [section "oldSub"] to [section "newSub"], as `git remote rename` does for the remote's section. It fails with ErrNotFound if the subsection is absent. As for RenameSection, an existing [section "newSub"] is not checked: `git remote rename` refuses one, and a caller doing the same checks f.Config().Subsections first.
func (*File) ReplaceAll ¶
ReplaceAll replaces all values of key with a single value, or adds it if key is absent, like `git config --replace-all <key> <value>`. The new value takes the place of the last old one.
func (*File) Set ¶
Set sets the value of key, like `git config <key> <value>`, adding it if absent. It fails with ErrMultipleValues if key has several values.
If the value is already set, the file is left unchanged. git would rewrite the line in its own format; keeping it is the one deliberate difference with git's edits. An implicit entry ("[a]\n\tk") is never already set, even for value "": it reads as true, and "k = " as false.
type FileError ¶
FileError reports a failure to load, lock or write a file. Path is the file concerned: the lock file for ErrLocked, as in git's "could not lock config file".
type Key ¶
type Key struct {
Section string
// Subsection is meaningful only if HasSubsection is set. git
// distinguishes an empty subsection ("a..k", header [a ""]) from none
// ("a.k", header [a]).
Subsection string
HasSubsection bool
Name string
}
Key is the canonical form of a key, as printed by `git config --list`: section and name in lower case, subsection verbatim.
func ParseKey ¶
ParseKey parses "section.name" or "section.subsection.name" as git does: the subsection is everything between the first and the last dot, section and name are lowered. A key git rejects is a *KeyError wrapping ErrInvalidKey: the section must hold only letters, digits and '-', the name must also start with a letter, and the subsection may hold anything but a newline or a NUL byte. Reads treat an invalid key as absent; only ParseKey and edits report it.
type KeyError ¶
KeyError reports an edit or a command-line entry that failed for a key or section name.
type Origin ¶
type Origin struct {
// Scope is the scope the entry was loaded for. Entries of Env.LoadFile,
// and of the Config of a File from Parse or Env.UpdateFile, have
// ScopeFile (git reports "command" for `git config -f`). A File from
// Env.UpdateScope has that scope.
Scope Scope
// File is the file that holds the entry, possibly an included one, or
// "" for the command line. Like git, an included file's relative path
// is appended to the including file's directory without cleaning it:
// "/home/u/.config/git/../work.inc". On Windows the separators are
// kept as given, where git shows some paths with '/'.
File string
Line int // 1-based; 0 for git -c
}
Origin tells where an entry comes from, as `git config --show-scope --show-origin` does.
type Scope ¶
type Scope int
Scope is one layer of git's configuration. Values from later scopes take precedence over earlier ones.
ScopeFile, the zero value, is not a layer: it marks entries of a file read on its own (Parse, Env.LoadFile, Env.UpdateFile), which may come from anyone. git reports such entries as "command"; this package keeps them apart so that they are never mistaken for the protected command scope.
const ( ScopeFile Scope = iota // a file read on its own, as with git config -f ScopeSystem // /etc/gitconfig or GIT_CONFIG_SYSTEM ScopeGlobal // ~/.gitconfig, the XDG file, or GIT_CONFIG_GLOBAL ScopeLocal // the repository's config ScopeWorktree // config.worktree, if extensions.worktreeConfig is enabled ScopeCommand // git -c, GIT_CONFIG_COUNT/KEY/VALUE; read-only )
type SyntaxError ¶
SyntaxError reports a file git refuses to parse. Msg describes the problem but never quotes the file's content, which may be a file that is not a configuration file at all, reached through an include.
func (*SyntaxError) Error ¶
func (e *SyntaxError) Error() string
type ValueError ¶
type ValueError struct {
Entry Entry
Type string // "bool", "int", "path"
Err error // the reason, e.g. strconv.ErrRange; may be nil
}
ValueError reports a value that cannot be read as the requested type. Its message quotes the value with %q, so that control characters in a value cannot reach a terminal.
func (*ValueError) Error ¶
func (e *ValueError) Error() string
func (*ValueError) Unwrap ¶
func (e *ValueError) Unwrap() error