mirror of https://github.com/spf13/afero.git
Add implementation for TempFile with wild card prefix
Signed-off-by: Illya Chekrygin <illya.chekrygin@gmail.com>
This commit is contained in:
parent
588a75ec4f
commit
e016ffbd1f
7
go.mod
7
go.mod
|
@ -1,3 +1,8 @@
|
||||||
module github.com/spf13/afero
|
module github.com/spf13/afero
|
||||||
|
|
||||||
require golang.org/x/text v0.3.0
|
require (
|
||||||
|
github.com/pkg/sftp v1.10.1
|
||||||
|
golang.org/x/text v0.3.0
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
18
go.sum
18
go.sum
|
@ -1,2 +1,20 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=
|
||||||
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
28
ioutil.go
28
ioutil.go
|
@ -22,6 +22,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -147,7 +148,7 @@ func reseed() uint32 {
|
||||||
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextSuffix() string {
|
func nextRandom() string {
|
||||||
randmu.Lock()
|
randmu.Lock()
|
||||||
r := rand
|
r := rand
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
|
@ -159,27 +160,36 @@ func nextSuffix() string {
|
||||||
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
return strconv.Itoa(int(1e9 + r%1e9))[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// TempFile creates a new temporary file in the directory dir
|
// TempFile creates a new temporary file in the directory dir,
|
||||||
// with a name beginning with prefix, opens the file for reading
|
// opens the file for reading and writing, and returns the resulting *os.File.
|
||||||
// and writing, and returns the resulting *File.
|
// The filename is generated by taking pattern and adding a random
|
||||||
|
// string to the end. If pattern includes a "*", the random string
|
||||||
|
// replaces the last "*".
|
||||||
// If dir is the empty string, TempFile uses the default directory
|
// If dir is the empty string, TempFile uses the default directory
|
||||||
// for temporary files (see os.TempDir).
|
// for temporary files (see os.TempDir).
|
||||||
// Multiple programs calling TempFile simultaneously
|
// Multiple programs calling TempFile simultaneously
|
||||||
// will not choose the same file. The caller can use f.Name()
|
// will not choose the same file. The caller can use f.Name()
|
||||||
// to find the pathname of the file. It is the caller's responsibility
|
// to find the pathname of the file. It is the caller's responsibility
|
||||||
// to remove the file when no longer needed.
|
// to remove the file when no longer needed.
|
||||||
func (a Afero) TempFile(dir, prefix string) (f File, err error) {
|
func (a Afero) TempFile(dir, pattern string) (f File, err error) {
|
||||||
return TempFile(a.Fs, dir, prefix)
|
return TempFile(a.Fs, dir, pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TempFile(fs Fs, dir, prefix string) (f File, err error) {
|
func TempFile(fs Fs, dir, pattern string) (f File, err error) {
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
dir = os.TempDir()
|
dir = os.TempDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var prefix, suffix string
|
||||||
|
if pos := strings.LastIndex(pattern, "*"); pos != -1 {
|
||||||
|
prefix, suffix = pattern[:pos], pattern[pos+1:]
|
||||||
|
} else {
|
||||||
|
prefix = pattern
|
||||||
|
}
|
||||||
|
|
||||||
nconflict := 0
|
nconflict := 0
|
||||||
for i := 0; i < 10000; i++ {
|
for i := 0; i < 10000; i++ {
|
||||||
name := filepath.Join(dir, prefix+nextSuffix())
|
name := filepath.Join(dir, prefix+nextRandom()+suffix)
|
||||||
f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
if nconflict++; nconflict > 10 {
|
if nconflict++; nconflict > 10 {
|
||||||
|
@ -211,7 +221,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
|
||||||
|
|
||||||
nconflict := 0
|
nconflict := 0
|
||||||
for i := 0; i < 10000; i++ {
|
for i := 0; i < 10000; i++ {
|
||||||
try := filepath.Join(dir, prefix+nextSuffix())
|
try := filepath.Join(dir, prefix+nextRandom())
|
||||||
err = fs.Mkdir(try, 0700)
|
err = fs.Mkdir(try, 0700)
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
if nconflict++; nconflict > 10 {
|
if nconflict++; nconflict > 10 {
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
|
|
||||||
package afero
|
package afero
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func checkSizePath(t *testing.T, path string, size int64) {
|
func checkSizePath(t *testing.T, path string, size int64) {
|
||||||
dir, err := testFS.Stat(path)
|
dir, err := testFS.Stat(path)
|
||||||
|
@ -110,3 +114,63 @@ func TestReadDir(t *testing.T) {
|
||||||
t.Fatalf("ReadDir %s: i-am-a-dir directory not found", dirname)
|
t.Fatalf("ReadDir %s: i-am-a-dir directory not found", dirname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTempFile(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
dir string
|
||||||
|
pattern string
|
||||||
|
}
|
||||||
|
tests := map[string]struct {
|
||||||
|
args args
|
||||||
|
want func(*testing.T, string)
|
||||||
|
}{
|
||||||
|
"foo": { // simple file name
|
||||||
|
args: args{
|
||||||
|
dir: "",
|
||||||
|
pattern: "foo",
|
||||||
|
},
|
||||||
|
want: func(t *testing.T, base string) {
|
||||||
|
if !strings.HasPrefix(base, "foo") || len(base) <= len("foo") {
|
||||||
|
t.Errorf("TempFile() file = %s, invalid file name", base)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"foo.bar": { // file name w/ ext
|
||||||
|
args: args{
|
||||||
|
dir: "",
|
||||||
|
pattern: "foo.bar",
|
||||||
|
},
|
||||||
|
want: func(t *testing.T, base string) {
|
||||||
|
if !strings.HasPrefix(base, "foo.bar") || len(base) <= len("foo.bar") {
|
||||||
|
t.Errorf("TempFile() file = %v, invalid file name", base)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"foo-*.bar": { // file name with wild card
|
||||||
|
args: args{
|
||||||
|
dir: "",
|
||||||
|
pattern: "foo-*.bar",
|
||||||
|
},
|
||||||
|
want: func(t *testing.T, base string) {
|
||||||
|
if !(strings.HasPrefix(base, "foo-") || strings.HasPrefix(base, "bar")) ||
|
||||||
|
len(base) <= len("foo-*.bar") {
|
||||||
|
t.Errorf("TempFile() file = %v, invalid file name", base)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tt := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
file, err := TempFile(NewMemMapFs(), tt.args.dir, tt.args.pattern)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("TempFile() error = %v, none expected", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if file == nil {
|
||||||
|
t.Errorf("TempFile() file = %v, should not be nil", file)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tt.want(t, filepath.Base(file.Name()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue