feat: add filecontent named mapper
This commit is contained in:
@@ -485,6 +485,7 @@ function `NamedMapper(name, mapper)`.
|
|||||||
| `existingfile` | An existing file. ~ expansion is applied. `-` is accepted for stdin, and will be passed unaltered. |
|
| `existingfile` | An existing file. ~ expansion is applied. `-` is accepted for stdin, and will be passed unaltered. |
|
||||||
| `existingdir` | An existing directory. ~ expansion is applied. |
|
| `existingdir` | An existing directory. ~ expansion is applied. |
|
||||||
| `counter` | Increment a numeric field. Useful for `-vvv`. Can accept `-s`, `--long` or `--long=N`. |
|
| `counter` | Increment a numeric field. Useful for `-vvv`. Can accept `-s`, `--long` or `--long=N`. |
|
||||||
|
| `filecontent` | Read the file at path into the field. ~ expansion is applied. `-` is accepted for stdin, and will be passed unaltered. |
|
||||||
|
|
||||||
|
|
||||||
Slices and maps treat type tags specially. For slices, the `type:""` tag
|
Slices and maps treat type tags specially. For slices, the `type:""` tag
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ func (r *Registry) RegisterDefaults() *Registry {
|
|||||||
RegisterName("existingfile", existingFileMapper(r)).
|
RegisterName("existingfile", existingFileMapper(r)).
|
||||||
RegisterName("existingdir", existingDirMapper(r)).
|
RegisterName("existingdir", existingDirMapper(r)).
|
||||||
RegisterName("counter", counterMapper()).
|
RegisterName("counter", counterMapper()).
|
||||||
|
RegisterName("filecontent", fileContentMapper(r)).
|
||||||
RegisterKind(reflect.Ptr, ptrMapper{r})
|
RegisterKind(reflect.Ptr, ptrMapper{r})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,6 +685,39 @@ func existingDirMapper(r *Registry) MapperFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fileContentMapper(r *Registry) MapperFunc {
|
||||||
|
return func(ctx *DecodeContext, target reflect.Value) error {
|
||||||
|
if target.Kind() != reflect.Slice && target.Elem().Kind() != reflect.Uint8 {
|
||||||
|
return fmt.Errorf("\"filecontent\" must be applied to []byte not %s", target.Type())
|
||||||
|
}
|
||||||
|
var path string
|
||||||
|
err := ctx.Scan.PopValueInto("file", &path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ctx.Value.Active || ctx.Value.Set {
|
||||||
|
// early return to avoid checking extra dirs that may not exist;
|
||||||
|
// this hack only works because the value provided on the cli is
|
||||||
|
// checked before the default value is checked (if default is set).
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
if path != "-" {
|
||||||
|
path = ExpandPath(path)
|
||||||
|
data, err = ioutil.ReadFile(path) //nolint:gosec
|
||||||
|
} else {
|
||||||
|
data, err = ioutil.ReadAll(os.Stdin)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
target.SetBytes(data)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ptrMapper struct {
|
type ptrMapper struct {
|
||||||
r *Registry
|
r *Registry
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -469,6 +469,24 @@ func TestFileMapper(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, os.Stdin, cli.File)
|
assert.Equal(t, os.Stdin, cli.File)
|
||||||
}
|
}
|
||||||
|
func TestFileContentMapper(t *testing.T) {
|
||||||
|
type CLI struct {
|
||||||
|
File []byte `type:"filecontent"`
|
||||||
|
}
|
||||||
|
var cli CLI
|
||||||
|
p := mustNew(t, &cli)
|
||||||
|
_, err := p.Parse([]string{"--file", "testdata/file.txt"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, []byte(`Hello world.`), cli.File)
|
||||||
|
p = mustNew(t, &cli)
|
||||||
|
_, err = p.Parse([]string{"--file", "testdata/missing.txt"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "missing.txt: no such file or directory")
|
||||||
|
p = mustNew(t, &cli)
|
||||||
|
_, err = p.Parse([]string{"--file", "testdata/"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "is a directory")
|
||||||
|
}
|
||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
func TestExistingFileMapper(t *testing.T) {
|
func TestExistingFileMapper(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user