git-lfs/lfshttp/lfshttp.go
Chris Darroch 2830d39ef4 avoid extra message format parsing where possible
Because the tr.Tr.Get() family of methods insert arguments
into printf(3)-style format strings after translating the
format string, we can in a few cases drop a surrounding call
to fmt.Sprintf() or a similar method, as those now take no
arguments and so are redundant.

Moreover, this will help us avoid situations where either
the translated string or the argument values interpolated
by tr.Tr.Get() produce an output string which itself happens
to contain character sequences that resemble Go format
specifiers (e.g., "%s", "%d", etc.)  In such cases passing the
string at runtime to a method such as fmt.Fprintf() will result
in the output containing a warning such as "%!s(MISSING)", which
is not ideal.

Note that in one case, in lfs/attribute.go, we can now also
simplify the format string to use standard format specifiers
instead of double-escaped ones (e.g., "%%q") since we can just
allow tr.Tr.Get() to do the interpolation.

We also take the opportunity to remove explicit leading or
trailing newlines from translation messages wherever it is
possible to convert the surrounding call to fmt.Print(),
fmt.Fprint(), fmt.Println(), or fmt.Fprintln().

Finally, in the commands/run.go file, we can replace two calls
to fmt.Fprintf() with fmt.Println() because they are just
printing output to os.Stdout, not os.Stderr, and in the
lfs/extension.go file, we can make better use of fmt.Errorf().

Note that at least one of these messages is not yet actually
passed as a translation string, but we will address that issue
in a subsequent commit.
2022-01-29 22:32:58 -08:00

92 lines
1.9 KiB
Go

package lfshttp
import (
"encoding/json"
"net/http"
"regexp"
"github.com/git-lfs/git-lfs/v3/config"
"github.com/git-lfs/git-lfs/v3/errors"
"github.com/git-lfs/git-lfs/v3/git"
"github.com/git-lfs/git-lfs/v3/tr"
)
var (
lfsMediaTypeRE = regexp.MustCompile(`\Aapplication/vnd\.git\-lfs\+json(;|\z)`)
jsonMediaTypeRE = regexp.MustCompile(`\Aapplication/json(;|\z)`)
)
type Context interface {
GitConfig() *git.Configuration
OSEnv() config.Environment
GitEnv() config.Environment
}
func NewContext(gitConf *git.Configuration, osEnv, gitEnv map[string]string) Context {
c := &testContext{gitConfig: gitConf}
if c.gitConfig == nil {
c.gitConfig = git.NewConfig("", "")
}
if osEnv != nil {
c.osEnv = testEnv(osEnv)
} else {
c.osEnv = make(testEnv)
}
if gitEnv != nil {
c.gitEnv = testEnv(gitEnv)
} else {
c.gitEnv = make(testEnv)
}
return c
}
type testContext struct {
gitConfig *git.Configuration
osEnv config.Environment
gitEnv config.Environment
}
func (c *testContext) GitConfig() *git.Configuration {
return c.gitConfig
}
func (c *testContext) OSEnv() config.Environment {
return c.osEnv
}
func (c *testContext) GitEnv() config.Environment {
return c.gitEnv
}
func IsDecodeTypeError(err error) bool {
_, ok := err.(*decodeTypeError)
return ok
}
type decodeTypeError struct {
Type string
}
func (e *decodeTypeError) TypeError() {}
func (e *decodeTypeError) Error() string {
return tr.Tr.Get("Expected JSON type, got: %q", e.Type)
}
func DecodeJSON(res *http.Response, obj interface{}) error {
ctype := res.Header.Get("Content-Type")
if !(lfsMediaTypeRE.MatchString(ctype) || jsonMediaTypeRE.MatchString(ctype)) {
return &decodeTypeError{Type: ctype}
}
err := json.NewDecoder(res.Body).Decode(obj)
res.Body.Close()
if err != nil {
return errors.Wrapf(err, tr.Tr.Get("Unable to parse HTTP response for %s %s", res.Request.Method, res.Request.URL))
}
return nil
}