-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"path" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
// PathHelper represents the application path-helper. Takes a configuration as input, and uses local | ||
// attributes to keep list of files and directories to compose PATH. | ||
type PathHelper struct { | ||
config *Config // parsed command-line flags | ||
files []string // slice of files in path.d | ||
directories []string // directories that will compose PATH | ||
} | ||
|
||
// logger for path-helper instance, skip printing when verbose is off. | ||
func (p *PathHelper) logger(format string, v ...interface{}) { | ||
if p.config.Verbose { | ||
fmt.Printf(fmt.Sprintf("# %s\n", format), v...) | ||
} | ||
} | ||
|
||
// append a direcotry in global list, making sure it skips duplicates when setting is enabled. | ||
func (p *PathHelper) append(directory string) { | ||
if p.config.SkipDuplicates { | ||
for _, d := range p.directories { | ||
if d == directory { | ||
p.logger("[WARN] Skipping entry '%s', is already defined.", directory) | ||
return | ||
} | ||
} | ||
} | ||
p.directories = append(p.directories, directory) | ||
} | ||
|
||
// globPathFiles load list of files in base directory. Returns errors when base directory does not | ||
// exist or when having issues to execute globing. | ||
func (p *PathHelper) globPathFiles() error { | ||
baseDir := p.config.BaseDir | ||
p.logger("Inspecting paths directory: '%s'", baseDir) | ||
if !dirExists(baseDir) { | ||
return fmt.Errorf("can't find base directory at '%s'", baseDir) | ||
} | ||
|
||
var err error | ||
pattern := path.Join(baseDir, "*") | ||
p.files, err = filepath.Glob(pattern) | ||
return err | ||
} | ||
|
||
// gatherPathDirs based in path files, read and inspect direcotories listed in those. Can return | ||
// errors related to reading files. | ||
func (p *PathHelper) gatherPathDirs() error { | ||
for _, file := range p.files { | ||
p.logger("File '%s'", file) | ||
directories, err := readLines(file) | ||
if err != nil { | ||
return fmt.Errorf("can't read file '%s': '%v'", file, err) | ||
} | ||
|
||
for _, directory := range directories { | ||
p.logger("\t- '%s'", directory) | ||
if p.config.SkipNotFound && !dirExists(directory) { | ||
p.logger("[WARN] Directory '%s' (%s) is not found! Skipping.", directory, file) | ||
continue | ||
} | ||
p.append(directory) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// pathDirsColonJoined return slice of direcotires joined by colon. | ||
func (p *PathHelper) pathDirsColonJoined() string { | ||
return strings.Join(p.directories, ":") | ||
} | ||
|
||
// RenderExpression print out the shell expression exporting PATH. Will forward errors from methods | ||
// listing and reading path files, and inspecting direcotories present found in those files. | ||
func (p *PathHelper) RenderExpression() (string, error) { | ||
if err := p.globPathFiles(); err != nil { | ||
return "", err | ||
} | ||
if err := p.gatherPathDirs(); err != nil { | ||
return "", err | ||
} | ||
|
||
return fmt.Sprintf("export PATH=\"%s\"", p.pathDirsColonJoined()), nil | ||
} | ||
|
||
// NewPathHelper instantiate a PathHelper type. | ||
func NewPathHelper(config *Config) *PathHelper { | ||
return &PathHelper{ | ||
config: config, | ||
files: []string{}, | ||
directories: []string{}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestPathHelper(t *testing.T) { | ||
config := &Config{Verbose: true, BaseDir: "./test/paths.d"} | ||
expectedJoinedPaths := "/a/a/a:/b/b/b:/c/c/c:/d/d/d" | ||
|
||
t.Run("without-duplicates", func(t *testing.T) { | ||
t.Run("inspecting-directories-and-files", func(t *testing.T) { | ||
inspectPathFilesAndDirectories(t, config, 1, expectedJoinedPaths) | ||
}) | ||
|
||
t.Run("RenderExpression", func(t *testing.T) { | ||
inspectRenderedExpression(t, config, expectedJoinedPaths) | ||
}) | ||
}) | ||
|
||
t.Run("with-duplicates", func(t *testing.T) { | ||
config.SkipDuplicates = true | ||
|
||
t.Run("inspecting-directories-and-files", func(t *testing.T) { | ||
inspectPathFilesAndDirectories(t, config, 1, expectedJoinedPaths) | ||
}) | ||
|
||
t.Run("RenderExpression", func(t *testing.T) { | ||
inspectRenderedExpression(t, config, expectedJoinedPaths) | ||
}) | ||
}) | ||
|
||
t.Run("with-skip-not-found", func(t *testing.T) { | ||
config.SkipDuplicates = true | ||
config.SkipNotFound = true | ||
|
||
t.Run("inspecting-directories-and-files", func(t *testing.T) { | ||
inspectPathFilesAndDirectories(t, config, 0, "") | ||
}) | ||
|
||
t.Run("RenderExpression", func(t *testing.T) { | ||
inspectRenderedExpression(t, config, "") | ||
}) | ||
}) | ||
} | ||
|
||
func inspectPathFilesAndDirectories( | ||
t *testing.T, | ||
config *Config, | ||
expectedLen int, | ||
expectedJoinedPaths string, | ||
) { | ||
p := NewPathHelper(config) | ||
err := p.globPathFiles() | ||
t.Logf("Error: '%#v", err) | ||
assert.NoError(t, err) | ||
t.Logf("Files: '%#v'", p.files) | ||
assert.True(t, len(p.files) >= expectedLen) | ||
|
||
err = p.gatherPathDirs() | ||
t.Logf("Error: '%#v", err) | ||
assert.NoError(t, err) | ||
t.Logf("Directories: '%#v'", p.directories) | ||
assert.True(t, len(p.directories) >= expectedLen) | ||
|
||
assert.Equal(t, expectedJoinedPaths, p.pathDirsColonJoined()) | ||
} | ||
|
||
func inspectRenderedExpression(t *testing.T, config *Config, expectedJoinedPaths string) { | ||
p := NewPathHelper(config) | ||
s, err := p.RenderExpression() | ||
assert.NoError(t, err) | ||
t.Logf("Expression: '%s'", s) | ||
assert.NotEmpty(t, s) | ||
assert.Equal(t, fmt.Sprintf("export PATH=\"%s\"", expectedJoinedPaths), s) | ||
} |