diff --git a/internal/tempdir/tempdir.go b/internal/tempdir/tempdir.go new file mode 100644 index 0000000..05d00a2 --- /dev/null +++ b/internal/tempdir/tempdir.go @@ -0,0 +1,90 @@ +// Copyright 2024 Matthew Rich . All rights reserved. + +package tempdir + +import ( + "os" + "path/filepath" + "strings" + "fmt" + "io/fs" + "log/slog" + "io" +) + +type Path string + +func (t *Path) ValidPath() bool { + if filepath.IsAbs(string(*t)) && strings.HasPrefix(string(*t), os.TempDir()) && len(*t) > 1 { + return true + } + return false +} + +func (t *Path) Create() (err error) { + slog.Info("tempdir.Create()", "path", string(*t)) + var TempDir string + TempDir, err = os.MkdirTemp("", string(*t)) + if err != nil || TempDir == "" { + err = fmt.Errorf("%w: Failed creating temp dir %s", err, TempDir) + } + *t = Path(TempDir) + return +} + +func (t *Path) Remove() { + slog.Info("tempdir.Remove()", "path", *t) + if t.ValidPath() { + os.RemoveAll(string(*t)) + } +} + +func (t *Path) CreateFileFromReader(name string, r io.Reader) (path string, err error) { + path = filepath.Join(string(*t), name) + _, statErr := os.Stat(path) + if os.IsNotExist(statErr) { + if file, createErr := os.Create(path); createErr == nil { + defer file.Close() + buf := make([]byte, 32*1024) + _, err = io.CopyBuffer(file, r, buf) + } else { + err = createErr + } + } + return +} + +func (t *Path) CreateFile(name string, content string) (err error) { + path := filepath.Join(string(*t), name) + _, statErr := os.Stat(path) + if os.IsNotExist(statErr) { + if file, createErr := os.Create(path); createErr == nil { + defer file.Close() + _, err = file.Write([]byte(content)) + } else { + err = createErr + } + } + return +} + +func (t *Path) Mkdir(name string, mode os.FileMode) (err error) { + var path string + if path, err = filepath.Abs(filepath.Join(string(*t), name)); err == nil { + if ! (*Path)(&path).ValidPath() { + return fmt.Errorf("Invalid path %s of %s", path, *t) + } + _, statErr := os.Stat(path) + if os.IsNotExist(statErr) { + err = os.Mkdir(path, mode) + } + } + return +} + +func (t *Path) DirFS() fs.FS { + if t.ValidPath() { + return os.DirFS(string(*t)) + } + return nil +} diff --git a/internal/tempdir/tempdir_test.go b/internal/tempdir/tempdir_test.go new file mode 100644 index 0000000..a342181 --- /dev/null +++ b/internal/tempdir/tempdir_test.go @@ -0,0 +1,31 @@ +// Copyright 2024 Matthew Rich . All rights reserved. + +package tempdir + +import ( + "github.com/stretchr/testify/assert" + "testing" + "os" + "path/filepath" +) + +func TestTempDir(t *testing.T) { + var TempDir Path = "testtempdir" + assert.Nil(t, TempDir.Create()) + assert.Contains(t, string(TempDir), "/tmp") + assert.Nil(t, TempDir.CreateFile("foo.txt", "testdata")) + stat, err := os.Stat(filepath.Join(string(TempDir), "foo.txt")) + assert.Nil(t, err) + assert.Equal(t, int64(8), stat.Size()) + assert.Nil(t, TempDir.Mkdir("bar", 0700)) + dirStat, err := os.Stat(filepath.Join(string(TempDir), "bar")) + assert.Nil(t, err) + assert.True(t, dirStat.IsDir()) + TempDir.Remove() + var InvalidTempDir Path = "" + assert.False(t, InvalidTempDir.ValidPath()) + assert.Nil(t, InvalidTempDir.Create()) + assert.Contains(t, string(InvalidTempDir), "/tmp") + assert.Greater(t, len(InvalidTempDir), 10) + InvalidTempDir.Remove() +}