Skip to content

Commit

Permalink
Exported utility function packages
Browse files Browse the repository at this point in the history
There was only the `internal/util` package, but the functions were well
suited for task runners that can be implemented by users to extend
snowsaw's capability to handle custom tasks.
To allow to use the utility functions the package has been moved to the
`pkg/util` parent package.

Epic GH-33
Resolves GH-66
  • Loading branch information
arcticicestudio committed Jul 13, 2019
1 parent 79afc12 commit 8531f47
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 68 deletions.
57 changes: 0 additions & 57 deletions internal/util/filesystem.go

This file was deleted.

30 changes: 19 additions & 11 deletions pkg/config/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import (
"path/filepath"
"reflect"

"github.com/fatih/color"
"github.com/imdario/mergo"

"github.com/arcticicestudio/snowsaw/internal/util"
"github.com/arcticicestudio/snowsaw/pkg/config/encoder"
"github.com/arcticicestudio/snowsaw/pkg/config/source/file"
"github.com/arcticicestudio/snowsaw/pkg/prt"
"github.com/arcticicestudio/snowsaw/pkg/util/filesystem"
)

// builder contains the current configuration building state.
Expand All @@ -39,17 +40,17 @@ func Load(files ...*file.File) *builder {

for _, f := range files {
// Convert to absolute path and check if file exists, otherwise ignore and check next.
f.Path, _ = util.AbsPath(f.Path)
if exists, _ := util.FileExists(f.Path); !exists {
prt.Debugf("Ignoring non-existent configuration file: %s", f.Path)
f.Path, _ = filepath.Abs(f.Path)
if exists, _ := filesystem.FileExists(f.Path); !exists {
prt.Debugf("Ignoring non-existent configuration file: %s", color.CyanString(f.Path))
continue
}

// Find matching encoder by file extension if not already set.
if f.Encoder == nil {
fileExt := filepath.Ext(f.Path)
if len(fileExt) <= 1 {
prt.Debugf("Ignoring configuration file without supported extension: %s", f.Path)
prt.Debugf("Ignoring configuration file without supported extension: %s", color.CyanString(f.Path))
continue
}

Expand All @@ -73,7 +74,8 @@ func Load(files ...*file.File) *builder {
}

// Into accepts a configuration struct pointer and populates it with the current config state.
func (s *builder) Into(c interface{}) error {
// The order of the files array is maintained when merging the configuration states into the struct is enabled.
func (s *builder) Into(c interface{}, merge bool) error {
base := reflect.New(reflect.TypeOf(c).Elem()).Interface()

for _, f := range s.Files {
Expand All @@ -82,15 +84,21 @@ func (s *builder) Into(c interface{}) error {
return err
}

if !merge {
// Decode the file content into the given base configuration state using the assigned encoder...
if encErr := f.Encoder.Decode(content, &c); encErr != nil {
return fmt.Errorf("%s: %v", f.Path, encErr)
}
continue
}

// ...or merge into the given base configuration state.
raw := base
// Decode the read content using the assigned encoder.
if encErr := f.Encoder.Decode(content, &raw); encErr != nil {
return fmt.Errorf("%s\n%v", f.Path, err)
return fmt.Errorf("%s: %v", f.Path, encErr)
}

// Merge decoded data into given base configuration state.
if encErr := mergo.Merge(c, raw, mergo.WithAppendSlice, mergo.WithOverride); encErr != nil {
return fmt.Errorf("%s\n%v", f.Path, err)
return fmt.Errorf("%s: %v", f.Path, encErr)
}
}

Expand Down
File renamed without changes.
103 changes: 103 additions & 0 deletions pkg/util/filesystem/filesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (C) 2017-present Arctic Ice Studio <[email protected]>
// Copyright (C) 2017-present Sven Greb <[email protected]>
//
// Project: snowsaw
// Repository: https://github.com/arcticicestudio/snowsaw
// License: MIT

// Author: Arctic Ice Studio <[email protected]>
// Author: Sven Greb <[email protected]>
// Since: 0.4.0

// Package filesystem provides utility functions related to filesystem actions.
package filesystem

import (
"fmt"
"os"

"github.com/mitchellh/go-homedir"
)

// DirExists checks if the directory at the path exists and is not a file.
// Returns true if the given path exists and is a directory, false otherwise.
// If an error occurs, false is returned along with the error.
func DirExists(path string) (bool, error) {
info, err := os.Stat(path)
if err == nil && info.IsDir() {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
if !info.IsDir() {
return false, fmt.Errorf("%s is a file", path)
}

return false, err
}

// ExpandPath expands environment variables and special elements like the tilde character for the given path.
// If an error occurs the original passed path is returned along with the corresponding error.
func ExpandPath(path string) (string, error) {
// Handle special case for Unix tilde character expansion.
expandedUserHomePath, err := homedir.Expand(path)
if err != nil {
return path, err
}

return os.ExpandEnv(expandedUserHomePath), nil
}

// FileExists checks if the file at the given path exists and is not a directory.
// If an error occurs, false is returned along with the corresponding error.
func FileExists(path string) (bool, error) {
info, err := os.Stat(path)
if err == nil && !info.IsDir() {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
if info.IsDir() {
return false, fmt.Errorf("%s is a directory", path)
}

return false, err
}

// IsFileWritable checks if the file at the given path is writable.
// If an error occurs, false is returned along with the corresponding error.
func IsFileWritable(path string) (bool, error) {
_, err := os.OpenFile(path, os.O_WRONLY, 0660)
if err != nil {
return false, err
}

return true, nil
}

// IsSymlink checks if the specified path is a symbolic link.
// If an error occurs, false is returned along with the corresponding error.
func IsSymlink(path string) (bool, error) {
fi, err := os.Lstat(path)
if err != nil {
return false, err
}

return fi.Mode()&os.ModeSymlink == os.ModeSymlink, nil
}

// NodeExists checks if the node at the given path exists.
// If an error occurs, false is returned along with the corresponding error.
func NodeExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}

return false, err
}

0 comments on commit 8531f47

Please sign in to comment.