Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for WildCard in TempFile Name Prefix #229

Merged
merged 1 commit into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
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 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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/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=
32 changes: 21 additions & 11 deletions ioutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"sort"
"strconv"
"strings"
"sync"
"time"
)
Expand Down Expand Up @@ -147,7 +148,7 @@ func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}

func nextSuffix() string {
func nextRandom() string {
randmu.Lock()
r := rand
if r == 0 {
Expand All @@ -159,27 +160,36 @@ func nextSuffix() string {
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}

// TempFile creates a new temporary file in the directory dir
// with a name beginning with prefix, opens the file for reading
// and writing, and returns the resulting *File.
// TempFile creates a new temporary file in the directory dir,
// opens the file for reading and writing, and returns the resulting *os.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
// for temporary files (see os.TempDir).
// Multiple programs calling TempFile simultaneously
// 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
// 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 remove the file when no longer needed.
func (a Afero) TempFile(dir, prefix string) (f File, err error) {
return TempFile(a.Fs, dir, prefix)
func (a Afero) TempFile(dir, pattern string) (f File, err error) {
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 == "" {
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
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)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
Expand Down Expand Up @@ -211,7 +221,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {

nconflict := 0
for i := 0; i < 10000; i++ {
try := filepath.Join(dir, prefix+nextSuffix())
try := filepath.Join(dir, prefix+nextRandom())
err = fs.Mkdir(try, 0700)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
Expand Down
66 changes: 65 additions & 1 deletion ioutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@

package afero

import "testing"
import (
"path/filepath"
"strings"
"testing"
)

func checkSizePath(t *testing.T, path string, size int64) {
dir, err := testFS.Stat(path)
Expand Down Expand Up @@ -110,3 +114,63 @@ func TestReadDir(t *testing.T) {
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()))
})
}
}