From abb546995405fc9f5f951b45693dadbda4a1be64 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Tue, 11 Jul 2023 17:00:44 -0700 Subject: [PATCH] wip --- ingredients/file/fileSymlink.go | 48 ++++++++++++++++++++++++++++++++- types/errors.go | 11 ++++---- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/ingredients/file/fileSymlink.go b/ingredients/file/fileSymlink.go index 212f682..81547c3 100644 --- a/ingredients/file/fileSymlink.go +++ b/ingredients/file/fileSymlink.go @@ -2,15 +2,29 @@ package file import ( "context" + "fmt" + "os" "path/filepath" "github.com/gogrlx/grlx/types" ) +// symlink creates a symlink at the given path +// +// the expected outcome is that name is a symlink pointing to target +// if force is true, then name will be replaced if it already exists +// if backupname is set, then name will be backed up to backupname if it already exists +// and force is true, and name is not a symlink +// if makedirs is true, then any missing directories in the path will be created +// if user is set, then the symlink will be owned by that user +// if group is set, then the symlink will be owned by that group +// if mode is set, then the symlink will be set to that mode +// if test is true, then the symlink will not be created, but the result will indicate +// what would have happened func (f File) symlink(ctx context.Context, test bool) (types.Result, error) { + // parameters to implement: // "name": "string", "target": "string", "force": "bool", "backupname": "string", // "makedirs": "bool", "user": "string", "group": "string", "mode": "string", - return f.undef() name, ok := f.params["name"].(string) if !ok { return types.Result{ @@ -28,5 +42,37 @@ func (f File) symlink(ctx context.Context, test bool) (types.Result, error) { Succeeded: false, Failed: true, }, types.ErrModifyRoot } + target, ok := f.params["target"].(string) + if !ok { + return types.Result{ + Succeeded: false, Failed: true, + }, types.ErrMissingTarget + } + target = filepath.Clean(target) + if target == "" { + return types.Result{ + Succeeded: false, Failed: true, + }, types.ErrMissingTarget + } + + nameStat, err := os.Stat(name) + if os.IsNotExist(err) { + if test { + return types.Result{ + Succeeded: true, Failed: false, + Changed: true, Notes: []fmt.Stringer{ + types.SimpleNote(fmt.Sprintf("symlink would be created %s -> %s", name, target)), + }, + }, nil + } + // check if it's not already a symlink + if nameStat.Mode()&os.ModeSymlink == 0 { + } + } else if err != nil { + return types.Result{ + Succeeded: false, Failed: true, + }, err + } + return f.undef() } diff --git a/types/errors.go b/types/errors.go index ceb9e7c..b229a76 100644 --- a/types/errors.go +++ b/types/errors.go @@ -26,9 +26,10 @@ var ( ErrCacheFailure = errors.New("file caching failed") ErrMissingContent = errors.New("file is missing content") - ErrFileNotFound = errors.New("file not found") - ErrHashMismatch = errors.New("file hash mismatch") - ErrDeleteRoot = errors.New("cannot delete root directory") - ErrModifyRoot = errors.New("cannot modify root directory") - ErrPathNotFound = errors.New("path not found") + ErrFileNotFound = errors.New("file not found") + ErrHashMismatch = errors.New("file hash mismatch") + ErrDeleteRoot = errors.New("cannot delete root directory") + ErrModifyRoot = errors.New("cannot modify root directory") + ErrMissingTarget = errors.New("target is missing") + ErrPathNotFound = errors.New("path not found") )