mirror of
https://github.com/cheat/cheat.git
synced 2024-11-23 22:41:35 +01:00
80c91cbdee
Integrate `go-git` into the application, and use it to `git clone` cheatsheets when the installer runs. Previously, the installer required that `git` be installed on the system `PATH`, so this change has to big advantages: 1. It removes that system dependency on `git` 2. It paves the way for implementing the `--update` command Additionally, `cheat` now performs a `--depth=1` clone when installing cheatsheets, which should at least somewhat improve installation times (especially on slow network connections).
78 lines
2.5 KiB
Plaintext
78 lines
2.5 KiB
Plaintext
Package warnings implements error handling with non-fatal errors (warnings).
|
|
|
|
import path: "gopkg.in/warnings.v0"
|
|
package docs: https://godoc.org/gopkg.in/warnings.v0
|
|
issues: https://github.com/go-warnings/warnings/issues
|
|
pull requests: https://github.com/go-warnings/warnings/pulls
|
|
|
|
A recurring pattern in Go programming is the following:
|
|
|
|
func myfunc(params) error {
|
|
if err := doSomething(...); err != nil {
|
|
return err
|
|
}
|
|
if err := doSomethingElse(...); err != nil {
|
|
return err
|
|
}
|
|
if ok := doAnotherThing(...); !ok {
|
|
return errors.New("my error")
|
|
}
|
|
...
|
|
return nil
|
|
}
|
|
|
|
This pattern allows interrupting the flow on any received error. But what if
|
|
there are errors that should be noted but still not fatal, for which the flow
|
|
should not be interrupted? Implementing such logic at each if statement would
|
|
make the code complex and the flow much harder to follow.
|
|
|
|
Package warnings provides the Collector type and a clean and simple pattern
|
|
for achieving such logic. The Collector takes care of deciding when to break
|
|
the flow and when to continue, collecting any non-fatal errors (warnings)
|
|
along the way. The only requirement is that fatal and non-fatal errors can be
|
|
distinguished programmatically; that is a function such as
|
|
|
|
IsFatal(error) bool
|
|
|
|
must be implemented. The following is an example of what the above snippet
|
|
could look like using the warnings package:
|
|
|
|
import "gopkg.in/warnings.v0"
|
|
|
|
func isFatal(err error) bool {
|
|
_, ok := err.(WarningType)
|
|
return !ok
|
|
}
|
|
|
|
func myfunc(params) error {
|
|
c := warnings.NewCollector(isFatal)
|
|
c.FatalWithWarnings = true
|
|
if err := c.Collect(doSomething()); err != nil {
|
|
return err
|
|
}
|
|
if err := c.Collect(doSomethingElse(...)); err != nil {
|
|
return err
|
|
}
|
|
if ok := doAnotherThing(...); !ok {
|
|
if err := c.Collect(errors.New("my error")); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
...
|
|
return c.Done()
|
|
}
|
|
|
|
For an example of a non-trivial code base using this library, see
|
|
gopkg.in/gcfg.v1
|
|
|
|
Rules for using warnings
|
|
|
|
- ensure that warnings are programmatically distinguishable from fatal
|
|
errors (i.e. implement an isFatal function and any necessary error types)
|
|
- ensure that there is a single Collector instance for a call of each
|
|
exported function
|
|
- ensure that all errors (fatal or warning) are fed through Collect
|
|
- ensure that every time an error is returned, it is one returned by a
|
|
Collector (from Collect or Done)
|
|
- ensure that Collect is never called after Done
|