Since we're about to do a v3.0.0 release, let's bump the version to v3.
Make this change automatically with the following command to avoid any
missed items:
git grep -l github.com/git-lfs/git-lfs/v2 | \
xargs sed -i -e 's!github.com/git-lfs/git-lfs/v2!github.com/git-lfs/git-lfs/v3!g'
When our go.mod file was introduced in commit
114e85c2002091eb415040923d872f8e4a4bc636 in PR #3208, the module
path chosen did not include a trailing /v2 component. However,
the Go modules specification now advises that module paths must
have a "major version suffix" which matches the release version.
We therefore add a /v2 suffix to our module path and all its
instances in import paths.
See also https://golang.org/ref/mod#major-version-suffixes for
details regarding the Go module system's major version suffix rule.
In order to support lazily loading the values stored in a user's `.gitconfig`,
we must wait until calling `*config.Configuration.loadGitConfig()` until it is
_absolutely necessary_.
To accomplish this, it was proposed that we introduce a wrapped variant of the
`*Environment` type, only for interacting with the `GitFetcher` that was
capable of supporting such beahvior.
As such, a new implementation of the `Environment` type must be defined. Since
previously there only existed the concrete type `*Environment`, this commit
demotes that down to `*enviornment`, and introduces the interface
`Environment`, which it implements.
Previously, to fetch data out of the `*config.Configuration` type, a reference
to a `Fetcher` was used, a-la:
```
cfg.Env.Get(...)
```
This is quite convenient, however, it forces the LFS client to implement
several methods more than once. Consider the interface:
```
type Fetcher interface {
Get(key string) (val string)
Bool(key string, def bool) (val bool)
// et. al.
}
```
In order to return typed information from a configuration instance, _each_
`Fetcher` must implement its own `N` methods for `Int`, `Bool`, etc.
To remedy this, the `Environment` type was introduced. It instead _has_ a
`Fetcher`, and defines its own type conversions, like so:
```
type Environment struct {
f Fetcher
}
func (e *Environment) Bool(key string, def bool) (val bool) { }
func (e *Environment) Int(key string, def int) (val int) { }
// et. al.
```
Now, the `config.Configuration` type holds a reference to an `Environment`, and
all type conversion methods are defined only once, saving time, and enforcing
consistency across multiple sources.