mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-09-12 00:02:30 +00:00
Update dependencies (#1951)
This commit is contained in:
26
vendor/github.com/spf13/afero/.travis.yml
generated
vendored
26
vendor/github.com/spf13/afero/.travis.yml
generated
vendored
@@ -1,26 +0,0 @@
|
||||
sudo: false
|
||||
language: go
|
||||
arch:
|
||||
- amd64
|
||||
- ppc64e
|
||||
|
||||
go:
|
||||
- "1.14"
|
||||
- "1.15"
|
||||
- "1.16"
|
||||
- tip
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
fast_finish: true
|
||||
|
||||
script:
|
||||
- go build -v ./...
|
||||
- go test -count=1 -cover -race -v ./...
|
||||
- go vet ./...
|
||||
- FILES=$(gofmt -s -l . zipfs sftpfs mem tarfs); if [[ -n "${FILES}" ]]; then echo "You have go format errors; gofmt your changes"; exit 1; fi
|
2
vendor/github.com/spf13/afero/README.md
generated
vendored
2
vendor/github.com/spf13/afero/README.md
generated
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
A FileSystem Abstraction System for Go
|
||||
|
||||
[](https://travis-ci.org/spf13/afero) [](https://ci.appveyor.com/project/spf13/afero) [](https://godoc.org/github.com/spf13/afero) [](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://github.com/spf13/afero/actions/workflows/test.yml) [](https://godoc.org/github.com/spf13/afero) [](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
# Overview
|
||||
|
||||
|
4
vendor/github.com/spf13/afero/afero.go
generated
vendored
4
vendor/github.com/spf13/afero/afero.go
generated
vendored
@@ -103,8 +103,8 @@ type Fs interface {
|
||||
|
||||
var (
|
||||
ErrFileClosed = errors.New("File is closed")
|
||||
ErrOutOfRange = errors.New("Out of range")
|
||||
ErrTooLarge = errors.New("Too large")
|
||||
ErrOutOfRange = errors.New("out of range")
|
||||
ErrTooLarge = errors.New("too large")
|
||||
ErrFileNotFound = os.ErrNotExist
|
||||
ErrFileExists = os.ErrExist
|
||||
ErrDestinationExists = os.ErrExist
|
||||
|
9
vendor/github.com/spf13/afero/appveyor.yml
generated
vendored
9
vendor/github.com/spf13/afero/appveyor.yml
generated
vendored
@@ -1,3 +1,5 @@
|
||||
# This currently does nothing. We have moved to GitHub action, but this is kept
|
||||
# until spf13 has disabled this project in AppVeyor.
|
||||
version: '{build}'
|
||||
clone_folder: C:\gopath\src\github.com\spf13\afero
|
||||
environment:
|
||||
@@ -6,10 +8,3 @@ build_script:
|
||||
- cmd: >-
|
||||
go version
|
||||
|
||||
go env
|
||||
|
||||
go get -v github.com/spf13/afero/...
|
||||
|
||||
go build -v github.com/spf13/afero/...
|
||||
test_script:
|
||||
- cmd: go test -count=1 -cover -race -v github.com/spf13/afero/...
|
||||
|
14
vendor/github.com/spf13/afero/basepath.go
generated
vendored
14
vendor/github.com/spf13/afero/basepath.go
generated
vendored
@@ -1,6 +1,7 @@
|
||||
package afero
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -8,7 +9,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ Lstater = (*BasePathFs)(nil)
|
||||
var (
|
||||
_ Lstater = (*BasePathFs)(nil)
|
||||
_ fs.ReadDirFile = (*BasePathFile)(nil)
|
||||
)
|
||||
|
||||
// The BasePathFs restricts all operations to a given path within an Fs.
|
||||
// The given file name to the operations on this Fs will be prepended with
|
||||
@@ -33,6 +37,14 @@ func (f *BasePathFile) Name() string {
|
||||
return strings.TrimPrefix(sourcename, filepath.Clean(f.path))
|
||||
}
|
||||
|
||||
func (f *BasePathFile) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||
if rdf, ok := f.File.(fs.ReadDirFile); ok {
|
||||
return rdf.ReadDir(n)
|
||||
|
||||
}
|
||||
return readDirFile{f.File}.ReadDir(n)
|
||||
}
|
||||
|
||||
func NewBasePathFs(source Fs, path string) Fs {
|
||||
return &BasePathFs{source: source, path: path}
|
||||
}
|
||||
|
1
vendor/github.com/spf13/afero/const_bsds.go
generated
vendored
1
vendor/github.com/spf13/afero/const_bsds.go
generated
vendored
@@ -11,6 +11,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build aix || darwin || openbsd || freebsd || netbsd || dragonfly
|
||||
// +build aix darwin openbsd freebsd netbsd dragonfly
|
||||
|
||||
package afero
|
||||
|
8
vendor/github.com/spf13/afero/const_win_unix.go
generated
vendored
8
vendor/github.com/spf13/afero/const_win_unix.go
generated
vendored
@@ -10,12 +10,8 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build !darwin
|
||||
// +build !openbsd
|
||||
// +build !freebsd
|
||||
// +build !dragonfly
|
||||
// +build !netbsd
|
||||
// +build !aix
|
||||
//go:build !darwin && !openbsd && !freebsd && !dragonfly && !netbsd && !aix
|
||||
// +build !darwin,!openbsd,!freebsd,!dragonfly,!netbsd,!aix
|
||||
|
||||
package afero
|
||||
|
||||
|
2
vendor/github.com/spf13/afero/httpFs.go
generated
vendored
2
vendor/github.com/spf13/afero/httpFs.go
generated
vendored
@@ -29,7 +29,7 @@ type httpDir struct {
|
||||
}
|
||||
|
||||
func (d httpDir) Open(name string) (http.File, error) {
|
||||
if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
|
||||
if filepath.Separator != '/' && strings.ContainsRune(name, filepath.Separator) ||
|
||||
strings.Contains(name, "\x00") {
|
||||
return nil, errors.New("http: invalid character in file path")
|
||||
}
|
||||
|
27
vendor/github.com/spf13/afero/internal/common/adapters.go
generated
vendored
Normal file
27
vendor/github.com/spf13/afero/internal/common/adapters.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright © 2022 Steve Francia <spf@spf13.com>.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package common
|
||||
|
||||
import "io/fs"
|
||||
|
||||
// FileInfoDirEntry provides an adapter from os.FileInfo to fs.DirEntry
|
||||
type FileInfoDirEntry struct {
|
||||
fs.FileInfo
|
||||
}
|
||||
|
||||
var _ fs.DirEntry = FileInfoDirEntry{}
|
||||
|
||||
func (d FileInfoDirEntry) Type() fs.FileMode { return d.FileInfo.Mode().Type() }
|
||||
|
||||
func (d FileInfoDirEntry) Info() (fs.FileInfo, error) { return d.FileInfo, nil }
|
38
vendor/github.com/spf13/afero/iofs.go
generated
vendored
38
vendor/github.com/spf13/afero/iofs.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package afero
|
||||
@@ -7,7 +8,10 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/afero/internal/common"
|
||||
)
|
||||
|
||||
// IOFS adopts afero.Fs to stdlib io/fs.FS
|
||||
@@ -66,14 +70,31 @@ func (iofs IOFS) Glob(pattern string) ([]string, error) {
|
||||
}
|
||||
|
||||
func (iofs IOFS) ReadDir(name string) ([]fs.DirEntry, error) {
|
||||
items, err := ReadDir(iofs.Fs, name)
|
||||
f, err := iofs.Fs.Open(name)
|
||||
if err != nil {
|
||||
return nil, iofs.wrapError("readdir", name, err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
if rdf, ok := f.(fs.ReadDirFile); ok {
|
||||
items, err := rdf.ReadDir(-1)
|
||||
if err != nil {
|
||||
return nil, iofs.wrapError("readdir", name, err)
|
||||
}
|
||||
sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
|
||||
return items, nil
|
||||
}
|
||||
|
||||
items, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, iofs.wrapError("readdir", name, err)
|
||||
}
|
||||
sort.Sort(byName(items))
|
||||
|
||||
ret := make([]fs.DirEntry, len(items))
|
||||
for i := range items {
|
||||
ret[i] = dirEntry{items[i]}
|
||||
ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
@@ -108,17 +129,6 @@ func (IOFS) wrapError(op, path string, err error) error {
|
||||
}
|
||||
}
|
||||
|
||||
// dirEntry provides adapter from os.FileInfo to fs.DirEntry
|
||||
type dirEntry struct {
|
||||
fs.FileInfo
|
||||
}
|
||||
|
||||
var _ fs.DirEntry = dirEntry{}
|
||||
|
||||
func (d dirEntry) Type() fs.FileMode { return d.FileInfo.Mode().Type() }
|
||||
|
||||
func (d dirEntry) Info() (fs.FileInfo, error) { return d.FileInfo, nil }
|
||||
|
||||
// readDirFile provides adapter from afero.File to fs.ReadDirFile needed for correct Open
|
||||
type readDirFile struct {
|
||||
File
|
||||
@@ -134,7 +144,7 @@ func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||
|
||||
ret := make([]fs.DirEntry, len(items))
|
||||
for i := range items {
|
||||
ret[i] = dirEntry{items[i]}
|
||||
ret[i] = common.FileInfoDirEntry{FileInfo: items[i]}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
10
vendor/github.com/spf13/afero/ioutil.go
generated
vendored
10
vendor/github.com/spf13/afero/ioutil.go
generated
vendored
@@ -141,7 +141,7 @@ func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
|
||||
// We generate random temporary file names so that there's a good
|
||||
// chance the file doesn't exist yet - keeps the number of tries in
|
||||
// TempFile to a minimum.
|
||||
var rand uint32
|
||||
var randNum uint32
|
||||
var randmu sync.Mutex
|
||||
|
||||
func reseed() uint32 {
|
||||
@@ -150,12 +150,12 @@ func reseed() uint32 {
|
||||
|
||||
func nextRandom() string {
|
||||
randmu.Lock()
|
||||
r := rand
|
||||
r := randNum
|
||||
if r == 0 {
|
||||
r = reseed()
|
||||
}
|
||||
r = r*1664525 + 1013904223 // constants from Numerical Recipes
|
||||
rand = r
|
||||
randNum = r
|
||||
randmu.Unlock()
|
||||
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
|
||||
if os.IsExist(err) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
randNum = reseed()
|
||||
randmu.Unlock()
|
||||
}
|
||||
continue
|
||||
@@ -226,7 +226,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
|
||||
if os.IsExist(err) {
|
||||
if nconflict++; nconflict > 10 {
|
||||
randmu.Lock()
|
||||
rand = reseed()
|
||||
randNum = reseed()
|
||||
randmu.Unlock()
|
||||
}
|
||||
continue
|
||||
|
30
vendor/github.com/spf13/afero/mem/file.go
generated
vendored
30
vendor/github.com/spf13/afero/mem/file.go
generated
vendored
@@ -18,15 +18,20 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/afero/internal/common"
|
||||
)
|
||||
|
||||
const FilePathSeparator = string(filepath.Separator)
|
||||
|
||||
var _ fs.ReadDirFile = &File{}
|
||||
|
||||
type File struct {
|
||||
// atomic requires 64-bit alignment for struct field access
|
||||
at int64
|
||||
@@ -183,10 +188,23 @@ func (f *File) Readdirnames(n int) (names []string, err error) {
|
||||
return names, err
|
||||
}
|
||||
|
||||
// Implements fs.ReadDirFile
|
||||
func (f *File) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||
fi, err := f.Readdir(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
di := make([]fs.DirEntry, len(fi))
|
||||
for i, f := range fi {
|
||||
di[i] = common.FileInfoDirEntry{FileInfo: f}
|
||||
}
|
||||
return di, nil
|
||||
}
|
||||
|
||||
func (f *File) Read(b []byte) (n int, err error) {
|
||||
f.fileData.Lock()
|
||||
defer f.fileData.Unlock()
|
||||
if f.closed == true {
|
||||
if f.closed {
|
||||
return 0, ErrFileClosed
|
||||
}
|
||||
if len(b) > 0 && int(f.at) == len(f.fileData.data) {
|
||||
@@ -214,7 +232,7 @@ func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
}
|
||||
|
||||
func (f *File) Truncate(size int64) error {
|
||||
if f.closed == true {
|
||||
if f.closed {
|
||||
return ErrFileClosed
|
||||
}
|
||||
if f.readOnly {
|
||||
@@ -236,7 +254,7 @@ func (f *File) Truncate(size int64) error {
|
||||
}
|
||||
|
||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
||||
if f.closed == true {
|
||||
if f.closed {
|
||||
return 0, ErrFileClosed
|
||||
}
|
||||
switch whence {
|
||||
@@ -251,7 +269,7 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
|
||||
}
|
||||
|
||||
func (f *File) Write(b []byte) (n int, err error) {
|
||||
if f.closed == true {
|
||||
if f.closed {
|
||||
return 0, ErrFileClosed
|
||||
}
|
||||
if f.readOnly {
|
||||
@@ -330,8 +348,8 @@ func (s *FileInfo) Size() int64 {
|
||||
|
||||
var (
|
||||
ErrFileClosed = errors.New("File is closed")
|
||||
ErrOutOfRange = errors.New("Out of range")
|
||||
ErrTooLarge = errors.New("Too large")
|
||||
ErrOutOfRange = errors.New("out of range")
|
||||
ErrTooLarge = errors.New("too large")
|
||||
ErrFileNotFound = os.ErrNotExist
|
||||
ErrFileExists = os.ErrExist
|
||||
ErrDestinationExists = os.ErrExist
|
||||
|
5
vendor/github.com/spf13/afero/memmap.go
generated
vendored
5
vendor/github.com/spf13/afero/memmap.go
generated
vendored
@@ -142,6 +142,11 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
// Dobule check that it doesn't exist.
|
||||
if _, ok := m.getData()[name]; ok {
|
||||
m.mu.Unlock()
|
||||
return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
|
||||
}
|
||||
item := mem.CreateDir(name)
|
||||
mem.SetMode(item, os.ModeDir|perm)
|
||||
m.getData()[name] = item
|
||||
|
2
vendor/github.com/spf13/afero/unionFile.go
generated
vendored
2
vendor/github.com/spf13/afero/unionFile.go
generated
vendored
@@ -65,7 +65,7 @@ func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) {
|
||||
if f.Layer != nil {
|
||||
n, err := f.Layer.ReadAt(s, o)
|
||||
if (err == nil || err == io.EOF) && f.Base != nil {
|
||||
_, err = f.Base.Seek(o+int64(n), os.SEEK_SET)
|
||||
_, err = f.Base.Seek(o+int64(n), io.SeekStart)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
10
vendor/github.com/spf13/afero/util.go
generated
vendored
10
vendor/github.com/spf13/afero/util.go
generated
vendored
@@ -25,6 +25,7 @@ import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/runes"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
@@ -158,16 +159,12 @@ func UnicodeSanitize(s string) string {
|
||||
|
||||
// Transform characters with accents into plain forms.
|
||||
func NeuterAccents(s string) string {
|
||||
t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
|
||||
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
|
||||
result, _, _ := transform.String(t, string(s))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func isMn(r rune) bool {
|
||||
return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks
|
||||
}
|
||||
|
||||
func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) {
|
||||
return FileContainsBytes(a.Fs, filename, subslice)
|
||||
}
|
||||
@@ -299,6 +296,9 @@ func IsEmpty(fs Fs, path string) (bool, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
list, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(list) == 0, nil
|
||||
}
|
||||
return fi.Size() == 0, nil
|
||||
|
4
vendor/github.com/spf13/viper/Makefile
generated
vendored
4
vendor/github.com/spf13/viper/Makefile
generated
vendored
@@ -16,7 +16,7 @@ endif
|
||||
|
||||
# Dependency versions
|
||||
GOTESTSUM_VERSION = 1.8.0
|
||||
GOLANGCI_VERSION = 1.45.2
|
||||
GOLANGCI_VERSION = 1.50.1
|
||||
|
||||
# Add the ability to override some variables
|
||||
# Use with care
|
||||
@@ -48,7 +48,7 @@ bin/golangci-lint: bin/golangci-lint-${GOLANGCI_VERSION}
|
||||
@ln -sf golangci-lint-${GOLANGCI_VERSION} bin/golangci-lint
|
||||
bin/golangci-lint-${GOLANGCI_VERSION}:
|
||||
@mkdir -p bin
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b ./bin/ v${GOLANGCI_VERSION}
|
||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b ./bin/ v${GOLANGCI_VERSION}
|
||||
@mv bin/golangci-lint "$@"
|
||||
|
||||
.PHONY: lint
|
||||
|
21
vendor/github.com/spf13/viper/README.md
generated
vendored
21
vendor/github.com/spf13/viper/README.md
generated
vendored
@@ -8,10 +8,10 @@
|
||||
[](https://github.com/avelino/awesome-go#configuration)
|
||||
[](https://repl.it/@sagikazarmark/Viper-example#main.go)
|
||||
|
||||
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
||||
[](https://github.com/spf13/viper/actions?query=workflow%3ACI)
|
||||
[](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://goreportcard.com/report/github.com/spf13/viper)
|
||||

|
||||

|
||||
[](https://pkg.go.dev/mod/github.com/spf13/viper)
|
||||
|
||||
**Go configuration with fangs!**
|
||||
@@ -40,8 +40,8 @@ go get github.com/spf13/viper
|
||||
|
||||
## What is Viper?
|
||||
|
||||
Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
|
||||
to work within an application, and can handle all types of configuration needs
|
||||
Viper is a complete configuration solution for Go applications including [12-Factor apps](https://12factor.net/#the_twelve_factors).
|
||||
It is designed to work within an application, and can handle all types of configuration needs
|
||||
and formats. It supports:
|
||||
|
||||
* setting defaults
|
||||
@@ -119,7 +119,7 @@ viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search
|
||||
viper.AddConfigPath(".") // optionally look for config in the working directory
|
||||
err := viper.ReadInConfig() // Find and read the config file
|
||||
if err != nil { // Handle errors reading the config file
|
||||
panic(fmt.Errorf("Fatal error config file: %w \n", err))
|
||||
panic(fmt.Errorf("fatal error config file: %w", err))
|
||||
}
|
||||
```
|
||||
|
||||
@@ -447,6 +447,13 @@ viper.SetConfigType("json") // because there is no file extension in a stream of
|
||||
err := viper.ReadRemoteConfig()
|
||||
```
|
||||
|
||||
#### etcd3
|
||||
```go
|
||||
viper.AddRemoteProvider("etcd3", "http://127.0.0.1:4001","/config/hugo.json")
|
||||
viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv"
|
||||
err := viper.ReadRemoteConfig()
|
||||
```
|
||||
|
||||
#### Consul
|
||||
You need to set a key to Consul key/value storage with JSON value containing your desired config.
|
||||
For example, create a Consul key/value store key `MY_CONSUL_KEY` with value:
|
||||
@@ -594,7 +601,7 @@ configuration level.
|
||||
|
||||
Viper can access array indices by using numbers in the path. For example:
|
||||
|
||||
```json
|
||||
```jsonc
|
||||
{
|
||||
"host": {
|
||||
"address": "localhost",
|
||||
@@ -622,7 +629,7 @@ GetInt("host.ports.1") // returns 6029
|
||||
Lastly, if there exists a key that matches the delimited key path, its value
|
||||
will be returned instead. E.g.
|
||||
|
||||
```json
|
||||
```jsonc
|
||||
{
|
||||
"datastore.metric.host": "0.0.0.0",
|
||||
"host": {
|
||||
|
29
vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
generated
vendored
29
vendor/github.com/spf13/viper/internal/encoding/toml/codec.go
generated
vendored
@@ -1,39 +1,16 @@
|
||||
//go:build viper_toml1
|
||||
// +build viper_toml1
|
||||
|
||||
package toml
|
||||
|
||||
import (
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
|
||||
type Codec struct{}
|
||||
|
||||
func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
|
||||
t, err := toml.TreeFromMap(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s, err := t.ToTomlString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []byte(s), nil
|
||||
return toml.Marshal(v)
|
||||
}
|
||||
|
||||
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||
tree, err := toml.LoadBytes(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmap := tree.ToMap()
|
||||
for key, value := range tmap {
|
||||
v[key] = value
|
||||
}
|
||||
|
||||
return nil
|
||||
return toml.Unmarshal(b, &v)
|
||||
}
|
||||
|
19
vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go
generated
vendored
19
vendor/github.com/spf13/viper/internal/encoding/toml/codec2.go
generated
vendored
@@ -1,19 +0,0 @@
|
||||
//go:build !viper_toml1
|
||||
// +build !viper_toml1
|
||||
|
||||
package toml
|
||||
|
||||
import (
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding.
|
||||
type Codec struct{}
|
||||
|
||||
func (Codec) Encode(v map[string]interface{}) ([]byte, error) {
|
||||
return toml.Marshal(v)
|
||||
}
|
||||
|
||||
func (Codec) Decode(b []byte, v map[string]interface{}) error {
|
||||
return toml.Unmarshal(b, &v)
|
||||
}
|
2
vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
generated
vendored
2
vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go
generated
vendored
@@ -1,6 +1,6 @@
|
||||
package yaml
|
||||
|
||||
// import "gopkg.in/yaml.v2"
|
||||
import "gopkg.in/yaml.v3"
|
||||
|
||||
// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding.
|
||||
type Codec struct{}
|
||||
|
14
vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go
generated
vendored
14
vendor/github.com/spf13/viper/internal/encoding/yaml/yaml2.go
generated
vendored
@@ -1,14 +0,0 @@
|
||||
//go:build viper_yaml2
|
||||
// +build viper_yaml2
|
||||
|
||||
package yaml
|
||||
|
||||
import yamlv2 "gopkg.in/yaml.v2"
|
||||
|
||||
var yaml = struct {
|
||||
Marshal func(in interface{}) (out []byte, err error)
|
||||
Unmarshal func(in []byte, out interface{}) (err error)
|
||||
}{
|
||||
Marshal: yamlv2.Marshal,
|
||||
Unmarshal: yamlv2.Unmarshal,
|
||||
}
|
14
vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go
generated
vendored
14
vendor/github.com/spf13/viper/internal/encoding/yaml/yaml3.go
generated
vendored
@@ -1,14 +0,0 @@
|
||||
//go:build !viper_yaml2
|
||||
// +build !viper_yaml2
|
||||
|
||||
package yaml
|
||||
|
||||
import yamlv3 "gopkg.in/yaml.v3"
|
||||
|
||||
var yaml = struct {
|
||||
Marshal func(in interface{}) (out []byte, err error)
|
||||
Unmarshal func(in []byte, out interface{}) (err error)
|
||||
}{
|
||||
Marshal: yamlv3.Marshal,
|
||||
Unmarshal: yamlv3.Unmarshal,
|
||||
}
|
4
vendor/github.com/spf13/viper/logger.go
generated
vendored
4
vendor/github.com/spf13/viper/logger.go
generated
vendored
@@ -7,8 +7,8 @@ import (
|
||||
)
|
||||
|
||||
// Logger is a unified interface for various logging use cases and practices, including:
|
||||
// - leveled logging
|
||||
// - structured logging
|
||||
// - leveled logging
|
||||
// - structured logging
|
||||
type Logger interface {
|
||||
// Trace logs a Trace event.
|
||||
//
|
||||
|
33
vendor/github.com/spf13/viper/util.go
generated
vendored
33
vendor/github.com/spf13/viper/util.go
generated
vendored
@@ -64,18 +64,25 @@ func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
|
||||
return nm
|
||||
}
|
||||
|
||||
func insensitiviseVal(val interface{}) interface{} {
|
||||
switch val.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
// nested map: cast and recursively insensitivise
|
||||
val = cast.ToStringMap(val)
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
case map[string]interface{}:
|
||||
// nested map: recursively insensitivise
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
case []interface{}:
|
||||
// nested array: recursively insensitivise
|
||||
insensitiveArray(val.([]interface{}))
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func insensitiviseMap(m map[string]interface{}) {
|
||||
for key, val := range m {
|
||||
switch val.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
// nested map: cast and recursively insensitivise
|
||||
val = cast.ToStringMap(val)
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
case map[string]interface{}:
|
||||
// nested map: recursively insensitivise
|
||||
insensitiviseMap(val.(map[string]interface{}))
|
||||
}
|
||||
|
||||
val = insensitiviseVal(val)
|
||||
lower := strings.ToLower(key)
|
||||
if key != lower {
|
||||
// remove old key (not lower-cased)
|
||||
@@ -86,6 +93,12 @@ func insensitiviseMap(m map[string]interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func insensitiveArray(a []interface{}) {
|
||||
for i, val := range a {
|
||||
a[i] = insensitiviseVal(val)
|
||||
}
|
||||
}
|
||||
|
||||
func absPathify(logger Logger, inPath string) string {
|
||||
logger.Info("trying to resolve absolute path", "path", inPath)
|
||||
|
||||
|
118
vendor/github.com/spf13/viper/viper.go
generated
vendored
118
vendor/github.com/spf13/viper/viper.go
generated
vendored
@@ -132,10 +132,10 @@ type DecoderConfigOption func(*mapstructure.DecoderConfig)
|
||||
// DecodeHook returns a DecoderConfigOption which overrides the default
|
||||
// DecoderConfig.DecodeHook value, the default is:
|
||||
//
|
||||
// mapstructure.ComposeDecodeHookFunc(
|
||||
// mapstructure.StringToTimeDurationHookFunc(),
|
||||
// mapstructure.StringToSliceHookFunc(","),
|
||||
// )
|
||||
// mapstructure.ComposeDecodeHookFunc(
|
||||
// mapstructure.StringToTimeDurationHookFunc(),
|
||||
// mapstructure.StringToSliceHookFunc(","),
|
||||
// )
|
||||
func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
|
||||
return func(c *mapstructure.DecoderConfig) {
|
||||
c.DecodeHook = hook
|
||||
@@ -156,18 +156,18 @@ func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
|
||||
//
|
||||
// For example, if values from the following sources were loaded:
|
||||
//
|
||||
// Defaults : {
|
||||
// "secret": "",
|
||||
// "user": "default",
|
||||
// "endpoint": "https://localhost"
|
||||
// }
|
||||
// Config : {
|
||||
// "user": "root"
|
||||
// "secret": "defaultsecret"
|
||||
// }
|
||||
// Env : {
|
||||
// "secret": "somesecretkey"
|
||||
// }
|
||||
// Defaults : {
|
||||
// "secret": "",
|
||||
// "user": "default",
|
||||
// "endpoint": "https://localhost"
|
||||
// }
|
||||
// Config : {
|
||||
// "user": "root"
|
||||
// "secret": "defaultsecret"
|
||||
// }
|
||||
// Env : {
|
||||
// "secret": "somesecretkey"
|
||||
// }
|
||||
//
|
||||
// The resulting config will have the following values:
|
||||
//
|
||||
@@ -300,7 +300,7 @@ func NewWithOptions(opts ...Option) *Viper {
|
||||
func Reset() {
|
||||
v = New()
|
||||
SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
|
||||
SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
|
||||
SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"}
|
||||
}
|
||||
|
||||
// TODO: make this lazy initialization instead
|
||||
@@ -419,15 +419,20 @@ type RemoteProvider interface {
|
||||
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"}
|
||||
|
||||
// SupportedRemoteProviders are universally supported remote providers.
|
||||
var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"}
|
||||
var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"}
|
||||
|
||||
// OnConfigChange sets the event handler that is called when a config file changes.
|
||||
func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) }
|
||||
|
||||
// OnConfigChange sets the event handler that is called when a config file changes.
|
||||
func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) {
|
||||
v.onConfigChange = run
|
||||
}
|
||||
|
||||
// WatchConfig starts watching a config file for changes.
|
||||
func WatchConfig() { v.WatchConfig() }
|
||||
|
||||
// WatchConfig starts watching a config file for changes.
|
||||
func (v *Viper) WatchConfig() {
|
||||
initWG := sync.WaitGroup{}
|
||||
initWG.Add(1)
|
||||
@@ -463,9 +468,8 @@ func (v *Viper) WatchConfig() {
|
||||
// we only care about the config file with the following cases:
|
||||
// 1 - if the config file was modified or created
|
||||
// 2 - if the real path to the config file changed (eg: k8s ConfigMap replacement)
|
||||
const writeOrCreateMask = fsnotify.Write | fsnotify.Create
|
||||
if (filepath.Clean(event.Name) == configFile &&
|
||||
event.Op&writeOrCreateMask != 0) ||
|
||||
(event.Has(fsnotify.Write) || event.Has(fsnotify.Create))) ||
|
||||
(currentConfigFile != "" && currentConfigFile != realConfigFile) {
|
||||
realConfigFile = currentConfigFile
|
||||
err := v.ReadInConfig()
|
||||
@@ -475,8 +479,7 @@ func (v *Viper) WatchConfig() {
|
||||
if v.onConfigChange != nil {
|
||||
v.onConfigChange(event)
|
||||
}
|
||||
} else if filepath.Clean(event.Name) == configFile &&
|
||||
event.Op&fsnotify.Remove != 0 {
|
||||
} else if filepath.Clean(event.Name) == configFile && event.Has(fsnotify.Remove) {
|
||||
eventsWG.Done()
|
||||
return
|
||||
}
|
||||
@@ -573,7 +576,7 @@ func (v *Viper) AddConfigPath(in string) {
|
||||
|
||||
// AddRemoteProvider adds a remote configuration source.
|
||||
// Remote Providers are searched in the order they are added.
|
||||
// provider is a string value: "etcd", "consul" or "firestore" are currently supported.
|
||||
// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported.
|
||||
// endpoint is the url. etcd requires http://ip:port consul requires ip:port
|
||||
// path is the path in the k/v store to retrieve configuration
|
||||
// To retrieve a config file called myapp.json from /configs/myapp.json
|
||||
@@ -604,7 +607,7 @@ func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
|
||||
|
||||
// AddSecureRemoteProvider adds a remote configuration source.
|
||||
// Secure Remote Providers are searched in the order they are added.
|
||||
// provider is a string value: "etcd", "consul" or "firestore" are currently supported.
|
||||
// provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported.
|
||||
// endpoint is the url. etcd requires http://ip:port consul requires ip:port
|
||||
// secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg
|
||||
// path is the path in the k/v store to retrieve configuration
|
||||
@@ -785,7 +788,8 @@ func (v *Viper) searchMapWithPathPrefixes(
|
||||
// isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere
|
||||
// on its path in the map.
|
||||
// e.g., if "foo.bar" has a value in the given map, it “shadows”
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
//
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string {
|
||||
var parentVal interface{}
|
||||
for i := 1; i < len(path); i++ {
|
||||
@@ -810,7 +814,8 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{})
|
||||
// isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere
|
||||
// in a sub-path of the map.
|
||||
// e.g., if "foo.bar" has a value in the given map, it “shadows”
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
//
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
|
||||
// unify input map
|
||||
var m map[string]interface{}
|
||||
@@ -835,7 +840,8 @@ func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string {
|
||||
// isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere
|
||||
// in the environment, when automatic env is on.
|
||||
// e.g., if "foo.bar" has a value in the environment, it “shadows”
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
//
|
||||
// "foo.bar.baz" in a lower-priority map
|
||||
func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
|
||||
var parentKey string
|
||||
for i := 1; i < len(path); i++ {
|
||||
@@ -856,11 +862,11 @@ func (v *Viper) isPathShadowedInAutoEnv(path []string) string {
|
||||
// would return a string slice for the key if the key's type is inferred by
|
||||
// the default value and the Get function would return:
|
||||
//
|
||||
// []string {"a", "b", "c"}
|
||||
// []string {"a", "b", "c"}
|
||||
//
|
||||
// Otherwise the Get function would return:
|
||||
//
|
||||
// "a b c"
|
||||
// "a b c"
|
||||
func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) }
|
||||
|
||||
func (v *Viper) SetTypeByDefaultValue(enable bool) {
|
||||
@@ -988,6 +994,13 @@ func (v *Viper) GetUint(key string) uint {
|
||||
return cast.ToUint(v.Get(key))
|
||||
}
|
||||
|
||||
// GetUint16 returns the value associated with the key as an unsigned integer.
|
||||
func GetUint16(key string) uint16 { return v.GetUint16(key) }
|
||||
|
||||
func (v *Viper) GetUint16(key string) uint16 {
|
||||
return cast.ToUint16(v.Get(key))
|
||||
}
|
||||
|
||||
// GetUint32 returns the value associated with the key as an unsigned integer.
|
||||
func GetUint32(key string) uint32 { return v.GetUint32(key) }
|
||||
|
||||
@@ -1137,9 +1150,8 @@ func (v *Viper) BindPFlags(flags *pflag.FlagSet) error {
|
||||
// BindPFlag binds a specific key to a pflag (as used by cobra).
|
||||
// Example (where serverCmd is a Cobra instance):
|
||||
//
|
||||
// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
|
||||
// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
|
||||
//
|
||||
// serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
|
||||
// Viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
|
||||
func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) }
|
||||
|
||||
func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error {
|
||||
@@ -1870,6 +1882,10 @@ func (v *Viper) getKeyValueConfig() error {
|
||||
return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'")
|
||||
}
|
||||
|
||||
if len(v.remoteProviders) == 0 {
|
||||
return RemoteConfigError("No Remote Providers")
|
||||
}
|
||||
|
||||
for _, rp := range v.remoteProviders {
|
||||
val, err := v.getRemoteConfig(rp)
|
||||
if err != nil {
|
||||
@@ -1896,6 +1912,10 @@ func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}
|
||||
|
||||
// Retrieve the first found remote configuration.
|
||||
func (v *Viper) watchKeyValueConfigOnChannel() error {
|
||||
if len(v.remoteProviders) == 0 {
|
||||
return RemoteConfigError("No Remote Providers")
|
||||
}
|
||||
|
||||
for _, rp := range v.remoteProviders {
|
||||
respc, _ := RemoteConfig.WatchChannel(rp)
|
||||
// Todo: Add quit channel
|
||||
@@ -1913,9 +1933,15 @@ func (v *Viper) watchKeyValueConfigOnChannel() error {
|
||||
|
||||
// Retrieve the first found remote configuration.
|
||||
func (v *Viper) watchKeyValueConfig() error {
|
||||
if len(v.remoteProviders) == 0 {
|
||||
return RemoteConfigError("No Remote Providers")
|
||||
}
|
||||
|
||||
for _, rp := range v.remoteProviders {
|
||||
val, err := v.watchRemoteConfig(rp)
|
||||
if err != nil {
|
||||
v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error())
|
||||
|
||||
continue
|
||||
}
|
||||
v.kvstore = val
|
||||
@@ -1958,9 +1984,10 @@ func (v *Viper) AllKeys() []string {
|
||||
|
||||
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
|
||||
// of key paths (used as a set, easier to manipulate than a []string):
|
||||
// - each path is merged into a single key string, delimited with v.keyDelim
|
||||
// - if a path is shadowed by an earlier value in the initial shadow map,
|
||||
// it is skipped.
|
||||
// - each path is merged into a single key string, delimited with v.keyDelim
|
||||
// - if a path is shadowed by an earlier value in the initial shadow map,
|
||||
// it is skipped.
|
||||
//
|
||||
// The resulting set of paths is merged to the given shadow set at the same time.
|
||||
func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool {
|
||||
if shadow != nil && prefix != "" && shadow[prefix] {
|
||||
@@ -2111,14 +2138,17 @@ func (v *Viper) getConfigFile() (string, error) {
|
||||
|
||||
// Debug prints all configuration registries for debugging
|
||||
// purposes.
|
||||
func Debug() { v.Debug() }
|
||||
func Debug() { v.Debug() }
|
||||
func DebugTo(w io.Writer) { v.DebugTo(w) }
|
||||
|
||||
func (v *Viper) Debug() {
|
||||
fmt.Printf("Aliases:\n%#v\n", v.aliases)
|
||||
fmt.Printf("Override:\n%#v\n", v.override)
|
||||
fmt.Printf("PFlags:\n%#v\n", v.pflags)
|
||||
fmt.Printf("Env:\n%#v\n", v.env)
|
||||
fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore)
|
||||
fmt.Printf("Config:\n%#v\n", v.config)
|
||||
fmt.Printf("Defaults:\n%#v\n", v.defaults)
|
||||
func (v *Viper) Debug() { v.DebugTo(os.Stdout) }
|
||||
|
||||
func (v *Viper) DebugTo(w io.Writer) {
|
||||
fmt.Fprintf(w, "Aliases:\n%#v\n", v.aliases)
|
||||
fmt.Fprintf(w, "Override:\n%#v\n", v.override)
|
||||
fmt.Fprintf(w, "PFlags:\n%#v\n", v.pflags)
|
||||
fmt.Fprintf(w, "Env:\n%#v\n", v.env)
|
||||
fmt.Fprintf(w, "Key/Value Store:\n%#v\n", v.kvstore)
|
||||
fmt.Fprintf(w, "Config:\n%#v\n", v.config)
|
||||
fmt.Fprintf(w, "Defaults:\n%#v\n", v.defaults)
|
||||
}
|
||||
|
4
vendor/github.com/spf13/viper/watch.go
generated
vendored
4
vendor/github.com/spf13/viper/watch.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
//go:build !js
|
||||
// +build !js
|
||||
//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
|
||||
// +build darwin dragonfly freebsd openbsd linux netbsd solaris windows
|
||||
|
||||
package viper
|
||||
|
||||
|
@@ -1,13 +1,19 @@
|
||||
// +build js,wasm
|
||||
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
|
||||
// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
|
||||
|
||||
package viper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
func newWatcher() (*watcher, error) {
|
||||
return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
type watcher struct {
|
||||
Events chan fsnotify.Event
|
||||
Errors chan error
|
||||
@@ -24,7 +30,3 @@ func (*watcher) Add(name string) error {
|
||||
func (*watcher) Remove(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newWatcher() (*watcher, error) {
|
||||
return &watcher{}, errors.New("fsnotify is not supported on WASM")
|
||||
}
|
Reference in New Issue
Block a user