grim/convey

Parents 4061dea8db1b
Children 4deb11e7ea44
rehash a bunch of object types to make things easier to deal with
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fs/copy.go Wed May 27 20:44:56 2020 -0500
@@ -0,0 +1,100 @@
+// Convey
+// Copyright 2016-2019 Gary Kramlich <grim@reaperworld.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package fs
+
+import (
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ log "github.com/sirupsen/logrus"
+)
+
+// CopyFile copies the contents from src to dst atomically.
+// If dst does not exist, CopyFile creates it with permissions perm.
+// If the copy fails, copyFile aborts and dst is preserved.
+func copyFile(src, dst string, perm os.FileMode) error {
+ in, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+ tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(tmp, in)
+ if err != nil {
+ tmp.Close()
+ os.Remove(tmp.Name())
+ return err
+ }
+ if err = tmp.Close(); err != nil {
+ os.Remove(tmp.Name())
+ return err
+ }
+ if err = os.Chmod(tmp.Name(), perm); err != nil {
+ os.Remove(tmp.Name())
+ return err
+ }
+ return os.Rename(tmp.Name(), dst)
+}
+
+func copyDir(src, dst string, perm os.FileMode) error {
+ absDst, err := filepath.Abs(dst)
+ if err != nil {
+ return err
+ }
+
+ dst = absDst
+
+ err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
+ log.Debugf("walk: path %q", path)
+
+ // make sure we're don't descend into our destination directory.
+ if strings.HasPrefix(path, absDst) {
+ log.Debugf("%q is in the destination %q", path, absDst)
+ return nil
+ }
+
+ // at this point we're going to do something so we need to the real
+ // destination name
+ realDst := filepath.Join(dst, strings.TrimPrefix(path, src))
+
+ log.Debugf("src %q; dst %q; realDst %q", path, dst, realDst)
+
+ // if path is a directory, create it
+ if info.IsDir() {
+ err := os.Mkdir(realDst, info.Mode())
+
+ // this will get called with the root of the volume, so we need to
+ // handle the error if it exists.
+ if os.IsExist(err) {
+ return nil
+ }
+
+ return err
+ }
+
+ // at this point we have a file so let's copy it
+ return copyFile(path, realDst, info.Mode())
+ })
+
+ return err
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fs/directory.go Wed May 27 20:44:56 2020 -0500
@@ -0,0 +1,87 @@
+// Convey
+// Copyright 2016-2020 Gary Kramlich <grim@reaperworld.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+// Package path provides utilities for handling filesystem paths and
+// objects.
+
+package fs
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type Directory struct {
+ path string
+}
+
+func NewDirectory(path string) (*Directory, error) {
+ if !strings.HasSuffix(path, "/") {
+ path += "/"
+ }
+
+ err := os.MkdirAll(path, 0700)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Directory{path: path}, nil
+}
+
+func (d *Directory) Path() string {
+ return d.path
+}
+
+func (d *Directory) Import(src, dst string) error {
+ file, err := os.Stat(src)
+ if err != nil {
+ return err
+ }
+
+ realDst := filepath.Join(d.path, dst)
+
+ if file.IsDir() {
+ log.Debugf("importing directory %q to %q", src, realDst)
+
+ return copyDir(src, realDst, file.Mode())
+ }
+
+ log.Debugf("importing file %q to %q", src, realDst)
+
+ return copyFile(src, realDst, file.Mode())
+}
+
+func (d *Directory) Export(src, dst string) error {
+ realSrc := filepath.Join(d.path, src)
+
+ file, err := os.Stat(realSrc)
+ if err != nil {
+ return err
+ }
+
+ if file.IsDir() {
+ log.Debugf("exporting directory %q to %q", realSrc, dst)
+
+ return copyDir(realSrc, dst, file.Mode())
+ }
+
+ log.Debugf("exporting file %q to %q", realSrc, dst)
+
+ return copyFile(realSrc, dst, file.Mode())
+}
--- a/workspace/fileio.go Wed May 27 19:45:40 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-// Convey
-// Copyright 2016-2019 Gary Kramlich <grim@reaperworld.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-package workspace
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- log "github.com/sirupsen/logrus"
-)
-
-// CopyFile copies the contents from src to dst atomically.
-// If dst does not exist, CopyFile creates it with permissions perm.
-// If the copy fails, CopyFile aborts and dst is preserved.
-func (ws *Workspace) copyFile(src, dst string, perm os.FileMode) error {
- in, err := os.Open(src)
- if err != nil {
- return err
- }
- defer in.Close()
- tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
- if err != nil {
- return err
- }
- _, err = io.Copy(tmp, in)
- if err != nil {
- tmp.Close()
- os.Remove(tmp.Name())
- return err
- }
- if err = tmp.Close(); err != nil {
- os.Remove(tmp.Name())
- return err
- }
- if err = os.Chmod(tmp.Name(), perm); err != nil {
- os.Remove(tmp.Name())
- return err
- }
- return os.Rename(tmp.Name(), dst)
-}
-
-func (ws *Workspace) copyDir(src, dst string, perm os.FileMode) error {
- absDst, err := filepath.Abs(dst)
- if err != nil {
- return err
- }
-
- dst = absDst
-
- err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
- log.Debugf("walk: path %q", path)
-
- // make sure we're copying files that are at the same level as convey.yml or
- // deeper.
- if !strings.HasPrefix(path, ws.parent) {
- return fmt.Errorf(
- "attempted to copy %q which is outside of the run context of %q",
- path,
- ws.parent,
- )
- }
-
- // make sure we're don't descend into our destination directory.
- if strings.HasPrefix(path, absDst) {
- log.Debugf("%q is in our destination %q", path, absDst)
- return nil
- }
-
- // at this point we're going to do something so we need to the real
- // destination name
- realDst := filepath.Join(dst, strings.TrimPrefix(path, ws.parent))
-
- log.Debugf("src %q; dst %q; realDst %q", path, dst, realDst)
-
- // if path is a directory, create it
- if info.IsDir() {
- err := os.Mkdir(realDst, info.Mode())
-
- // this will get called with the root of the volume, so we need to
- // handle the error if it exists.
- if os.IsExist(err) {
- return nil
- }
-
- return err
- }
-
- // at this point we have a file so let's copy it
- return ws.copyFile(path, realDst, info.Mode())
- })
-
- return err
-}
--- a/workspace/taskdir.go Wed May 27 19:45:40 2020 -0500
+++ b/workspace/taskdir.go Wed May 27 20:44:56 2020 -0500
@@ -17,70 +17,11 @@
package workspace
import (
- "os"
"path/filepath"
- "strings"
- log "github.com/sirupsen/logrus"
+ "keep.imfreedom.org/grim/convey/fs"
)
-type TaskDirectory struct {
- path string
- ws *Workspace
-}
-
-func (ws *Workspace) CreateTaskDirectory(name string) (*TaskDirectory, error) {
- dir := filepath.Join(ws.path, name)
- if !strings.HasSuffix(dir, "/") {
- dir += "/"
- }
-
- err := os.MkdirAll(dir, 0700)
-
- return &TaskDirectory{
- path: dir,
- ws: ws,
- }, err
+func (ws *Workspace) CreateTaskDirectory(name string) (*fs.Directory, error) {
+ return fs.NewDirectory(filepath.Join(ws.path, name))
}
-
-func (td *TaskDirectory) Import(src, dst string) error {
- file, err := os.Stat(src)
- if err != nil {
- return err
- }
-
- realDst := filepath.Join(td.path, dst)
-
- if file.IsDir() {
- log.Debugf("importing directory %q to %q", src, realDst)
-
- return td.ws.copyDir(src, realDst, file.Mode())
- }
-
- log.Debugf("importing file %q to %q", src, realDst)
-
- return td.ws.copyFile(src, realDst, file.Mode())
-}
-
-func (td *TaskDirectory) Export(src, dst string) error {
- realSrc := filepath.Join(td.path, src)
-
- file, err := os.Stat(realSrc)
- if err != nil {
- return err
- }
-
- if file.IsDir() {
- log.Debugf("importing directory %q to %q", realSrc, dst)
-
- return td.ws.copyDir(realSrc, dst, file.Mode())
- }
-
- log.Debugf("importing file %q to %q", realSrc, dst)
-
- return td.ws.copyFile(realSrc, dst, file.Mode())
-}
-
-func (td *TaskDirectory) Path() string {
- return td.path
-}
--- a/workspace/volume.go Wed May 27 19:45:40 2020 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-// Convey
-// Copyright 2016-2019 Gary Kramlich <grim@reaperworld.com>
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-package workspace
-
-import (
- "os"
- "path/filepath"
-
- log "github.com/sirupsen/logrus"
-)
-
-type Volume struct {
- path string
- ws *Workspace
-}
-
-func (vol *Volume) Import(src, dst string) error {
- file, err := os.Stat(src)
- if err != nil {
- return err
- }
-
- realDst := filepath.Join(vol.path, dst)
-
- if file.IsDir() {
- log.Debugf("importing directory %q to %q", src, realDst)
-
- return vol.ws.copyDir(src, realDst, file.Mode())
- }
-
- log.Debugf("importing file %q to %q", src, realDst)
-
- return vol.ws.copyFile(src, realDst, file.Mode())
-}
-
-func (vol *Volume) Export(src, dst string) error {
- realSrc := filepath.Join(vol.path, src)
-
- file, err := os.Stat(realSrc)
- if err != nil {
- return err
- }
-
- if file.IsDir() {
- log.Debugf("importing directory %q to %q", realSrc, dst)
-
- return vol.ws.copyDir(realSrc, dst, file.Mode())
- }
-
- log.Debugf("importing file %q to %q", realSrc, dst)
-
- return vol.ws.copyFile(realSrc, dst, file.Mode())
-}
-
-func (vol *Volume) Path() string {
- return vol.path
-}
--- a/workspace/workspace.go Wed May 27 19:45:40 2020 -0500
+++ b/workspace/workspace.go Wed May 27 20:44:56 2020 -0500
@@ -22,13 +22,15 @@
"path/filepath"
log "github.com/sirupsen/logrus"
+
+ "keep.imfreedom.org/grim/convey/fs"
)
type Workspace struct {
parent string
root string
path string
- volume *Volume
+ volume *fs.Directory
}
func New(parent string) (*Workspace, error) {
@@ -43,8 +45,7 @@
return nil, err
}
- volumePath := filepath.Join(path, "volume")
- err = os.Mkdir(volumePath, 0700)
+ volume, err := fs.NewDirectory(filepath.Join(path, "volume"))
if err != nil {
return nil, err
}
@@ -53,11 +54,7 @@
parent: parent,
root: root,
path: path,
- }
-
- workspace.volume = &Volume{
- path: volumePath,
- ws: workspace,
+ volume: volume,
}
return workspace, nil
@@ -80,6 +77,6 @@
return ws.path
}
-func (ws *Workspace) Volume() *Volume {
+func (ws *Workspace) Volume() *fs.Directory {
return ws.volume
}