Skip to content

Commit

Permalink
🐛 Adding ability to handle a custom rule directory (#132)
Browse files Browse the repository at this point in the history
* 🐛 Adding ability to handle a custom rule directory

Signed-off-by: Shawn Hurley <shawn@hurley.page>

* when handeling files during copy ignore hidden/dot files

Signed-off-by: Shawn Hurley <shawn@hurley.page>

---------

Signed-off-by: Shawn Hurley <shawn@hurley.page>
  • Loading branch information
shawn-hurley authored Jan 16, 2024
1 parent 86942ac commit 20af46f
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 25 deletions.
100 changes: 75 additions & 25 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"strings"

"github.com/go-logr/logr"
"github.com/konveyor-ecosystem/kantra/cmd/internal/hiddenfile"
"github.com/konveyor/analyzer-lsp/engine"
outputv1 "github.com/konveyor/analyzer-lsp/output/v1/konveyor"
"github.com/konveyor/analyzer-lsp/provider"
Expand Down Expand Up @@ -520,7 +521,6 @@ func (a *analyzeCommand) getRulesVolumes() (map[string]string, error) {
return nil, nil
}
rulesVolumes := make(map[string]string)
rulesetNeeded := false
tempDir, err := os.MkdirTemp("", "analyze-rules-")
if err != nil {
a.log.V(1).Error(err, "failed to create temp dir", "path", tempDir)
Expand All @@ -540,39 +540,78 @@ func (a *analyzeCommand) getRulesVolumes() (map[string]string, error) {
if isXMLFile(r) {
continue
}
rulesetNeeded = true
destFile := filepath.Join(tempDir, fmt.Sprintf("rules%d.yaml", i))
err := copyFileContents(r, destFile)
if err != nil {
a.log.V(1).Error(err, "failed to move rules file", "src", r, "dest", destFile)
return nil, err
}

} else {
if !a.enableDefaultRulesets {
rulesVolumes[r] = path.Join(CustomRulePath, filepath.Base(r))
} else {
rulesVolumes[r] = path.Join(RulesMountPath, filepath.Base(r))
a.log.V(5).Info("copied file to rule dir", "added file", r, "destFile", destFile)
err = a.createTempRuleSet(tempDir, "custom-ruleset")
if err != nil {
return nil, err
}

}
}
if rulesetNeeded {
tempRulesetPath := filepath.Join(tempDir, "ruleset.yaml")
err = createTempRuleSet(tempRulesetPath)
if err != nil {
a.log.V(1).Error(err, "failed to create temp ruleset", "path", tempRulesetPath)
return nil, err
}
if !a.enableDefaultRulesets {
rulesVolumes[tempDir] = path.Join(CustomRulePath, filepath.Base(tempDir))
} else {
rulesVolumes[tempDir] = path.Join(RulesMountPath, filepath.Base(tempDir))
a.log.V(5).Info("coping dir", "directory", r)
err = filepath.WalkDir(r, func(path string, d fs.DirEntry, err error) error {
if path == r {
return nil
}
if d.IsDir() {
// This will create the new dir
a.handleDir(path, tempDir, r)
} else {
// If we are unable to get the file attributes, probably safe to assume this is not a
// valid rule or ruleset and lets skip it for now.
if isHidden, err := hiddenfile.IsHidden(d.Name()); isHidden || err != nil {
a.log.V(5).Info("skipping hidden file", "path", path, "error", err)
return nil
}
relpath, err := filepath.Rel(r, path)
if err != nil {
return err
}
destFile := filepath.Join(tempDir, relpath)
a.log.V(5).Info("copying file main", "source", path, "dest", destFile)
err = copyFileContents(path, destFile)
if err != nil {
a.log.V(1).Error(err, "failed to move rules file", "src", r, "dest", destFile)
return err
}
}
return nil
})
if err != nil {
a.log.V(1).Error(err, "failed to move rules file", "src", r)
return nil, err
}
}
}
rulesVolumes[tempDir] = path.Join(CustomRulePath, filepath.Base(tempDir))

return rulesVolumes, nil
}

func (a *analyzeCommand) handleDir(p string, tempDir string, basePath string) error {
newDir, err := filepath.Rel(basePath, p)
if err != nil {
return err
}
tempDir = filepath.Join(tempDir, newDir)
a.log.Info("creating nested tmp dir", "tempDir", tempDir, "newDir", newDir)
err = os.Mkdir(tempDir, 0777)
if err != nil {
return err
}
a.log.V(5).Info("create temp rule set for dir", "dir", tempDir)
err = a.createTempRuleSet(tempDir, filepath.Base(p))
if err != nil {
a.log.V(1).Error(err, "failed to create temp ruleset", "path", tempDir)
return err
}
return err
}

func copyFileContents(src string, dst string) (err error) {
source, err := os.Open(src)
if err != nil {
Expand All @@ -591,16 +630,24 @@ func copyFileContents(src string, dst string) (err error) {
return nil
}

func createTempRuleSet(path string) error {
func (a analyzeCommand) createTempRuleSet(path string, name string) error {
a.log.Info("createing temp ruleset ", "path", path, "name", name)
_, err := os.Stat(path)
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
tempRuleSet := engine.RuleSet{
Name: "ruleset",
Name: name,
Description: "temp ruleset",
}
yamlData, err := yaml.Marshal(&tempRuleSet)
if err != nil {
return err
}
err = os.WriteFile(path, yamlData, os.ModePerm)
err = os.WriteFile(filepath.Join(path, "ruleset.yaml"), yamlData, os.ModePerm)
if err != nil {
return err
}
Expand Down Expand Up @@ -650,10 +697,13 @@ func (a *analyzeCommand) RunAnalysis(ctx context.Context, xmlOutputDir string) e
if a.enableDefaultRulesets {
args = append(args,
fmt.Sprintf("--rules=%s/", RulesetPath))
} else {
}

if len(a.rules) > 0 {
args = append(args,
fmt.Sprintf("--rules=%s/", CustomRulePath))
}

if a.jaegerEndpoint != "" {
args = append(args, "--enable-jaeger")
args = append(args, "--jaeger-endpoint")
Expand Down
14 changes: 14 additions & 0 deletions cmd/internal/hiddenfile/hidden_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build !windows && !windows
// +build !windows,!windows

package hiddenfile

const dotCharacter = 46

func IsHidden(name string) (bool, error) {
if name[0] == dotCharacter {
return true, nil
}

return false, nil
}
40 changes: 40 additions & 0 deletions cmd/internal/hiddenfile/hidden_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//go:build windows
// +build windows

package hiddenfile

import (
"path/filepath"
"syscall"
)

const dotCharacter = 46

// isHidden checks if a file is hidden on Windows.
func IsHidden(name string) (bool, error) {
// dotfiles also count as hidden (if you want)
if name[0] == dotCharacter {
return true, nil
}

absPath, err := filepath.Abs(name)
if err != nil {
return false, err
}

// Appending `\\?\` to the absolute path helps with
// preventing 'Path Not Specified Error' when accessing
// long paths and filenames
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd
pointer, err := syscall.UTF16PtrFromString(`\\?\` + absPath)
if err != nil {
return false, err
}

attributes, err := syscall.GetFileAttributes(pointer)
if err != nil {
return false, err
}

return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil
}

0 comments on commit 20af46f

Please sign in to comment.