Skip to content

Commit

Permalink
cmd: fix input/output directory edge cases and platform-specific oper…
Browse files Browse the repository at this point in the history
…ators in paths, fixes #438
  • Loading branch information
tdewolff committed Oct 4, 2021
1 parent 4d06866 commit 5f59503
Showing 1 changed file with 29 additions and 50 deletions.
79 changes: 29 additions & 50 deletions cmd/minify/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/url"
"os"
"os/signal"
"path"
"path/filepath"
"regexp"
"runtime"
Expand Down Expand Up @@ -79,7 +78,7 @@ func NewTask(root, input, output string, sync bool) (Task, error) {
if err != nil {
return Task{}, err
}
t.dst = path.Join(output, path.Base(root), filepath.ToSlash(rel))
t.dst = filepath.Join(output, rel)
}
return t, nil
}
Expand Down Expand Up @@ -300,22 +299,31 @@ func run() int {
////////////////

for i, input := range inputs {
inputs[i] = sanitizePath(input)
inputs[i] = filepath.Clean(input)
}

// set output, empty means stdout, ending in slash means a directory, otherwise a file
dirDst := false
if output != "" {
dirSrc := 1 < len(inputs) || len(inputs) == 1 && inputs[0][len(inputs[0])-1] == '/'
if !bundle && dirSrc && output[len(output)-1] != '/' {
output += "/"
dirDst := output[len(output)-1] == '/'
if !dirDst {
if 1 < len(inputs) && !bundle {
dirDst = true
} else if info, err := os.Lstat(inputs[0]); err == nil && !bundle && info.Mode().IsDir() && info.Mode()&os.ModeSymlink == 0 {
dirDst = true
} else if info, err := os.Lstat(output); err == nil && info.Mode().IsDir() && info.Mode()&os.ModeSymlink == 0 {
dirDst = true
}
}
output = sanitizePath(output)
dirDst = output[len(output)-1] == '/'
if dirDst && bundle {
Error.Println("--bundle requires destination to be stdout or a file")
return 1
}

output = filepath.Clean(output)
if dirDst {
output += "/"
}
} else if 1 < len(inputs) {
Error.Println("must specify --bundle for multiple input files with stdout destination")
return 1
Expand Down Expand Up @@ -440,7 +448,7 @@ func run() int {
changes = nil
break
}
file = sanitizePath(file)
file = filepath.Clean(file)

// find longest common path among roots
root := ""
Expand Down Expand Up @@ -499,33 +507,14 @@ func minifyWorker(chanTasks <-chan Task, chanFails chan<- int) {
chanFails <- fails
}

func sanitizePath(p string) string {
p = filepath.ToSlash(p) // replace \ with / for Windows
isCur := path.Base(p) == "."
isDir := p[len(p)-1] == '/' || isCur
p = path.Clean(p)
if p == "." {
return "./"
}
if isDir {
p += "/"
} else if info, err := os.Lstat(p); err == nil && info.Mode().IsDir() && info.Mode()&os.ModeSymlink == 0 {
p += "/"
}
if isCur {
p += "./"
}
return p
}

func fileMatches(filename string) bool {
if pattern != nil && !pattern.MatchString(filename) {
return false
} else if mimetype != "" {
return true
}

ext := path.Ext(filename)
ext := filepath.Ext(filename)
if 0 < len(ext) {
ext = ext[1:]
}
Expand All @@ -535,22 +524,12 @@ func fileMatches(filename string) bool {
return true
}

//type DirEntry struct {
// fs.FileInfo
//}
//
//func (d DirEntry) Type() fs.FileMode {
// return d.Mode().Type()
//}
//
//func (d DirEntry) Info() (fs.FileInfo, error) {
// return d.FileInfo, nil
//}

func createTasks(inputs []string, output string) ([]Task, []string, error) {
tasks := []Task{}
roots := []string{}
for _, input := range inputs {
root := filepath.Dir(input)

var info os.FileInfo
var err error
if !preserveLinks {
Expand All @@ -567,15 +546,15 @@ func createTasks(inputs []string, output string) ([]Task, []string, error) {
Warning.Println("--sync not specified, omitting symbolic link", input)
continue
}
task, err := NewTask(path.Dir(input), input, output, true)
task, err := NewTask(root, input, output, true)
if err != nil {
return nil, nil, err
}
tasks = append(tasks, task)
} else if info.Mode().IsRegular() {
valid := pattern == nil || pattern.MatchString(info.Name())
if valid || sync {
task, err := NewTask(path.Dir(input), input, output, !valid)
task, err := NewTask(root, input, output, !valid)
if err != nil {
return nil, nil, err
}
Expand All @@ -600,7 +579,7 @@ func createTasks(inputs []string, output string) ([]Task, []string, error) {
}
return nil
}
path = sanitizePath(path)
path = filepath.Clean(path)

if !preserveLinks && d.Type()&os.ModeSymlink != 0 {
// follow and dereference symlinks
Expand All @@ -620,15 +599,15 @@ func createTasks(inputs []string, output string) ([]Task, []string, error) {
Warning.Println("--sync not specified, omitting symbolic link", path)
return nil
}
task, err := NewTask(input, path, output, true)
task, err := NewTask(root, path, output, true)
if err != nil {
return err
}
tasks = append(tasks, task)
} else if d.Type().IsRegular() {
valid := fileMatches(d.Name())
if valid || sync {
task, err := NewTask(input, path, output, !valid)
task, err := NewTask(root, path, output, !valid)
if err != nil {
return err
}
Expand All @@ -637,7 +616,7 @@ func createTasks(inputs []string, output string) ([]Task, []string, error) {
}
return nil
}
if err := WalkDir(DirFS("."), path.Clean(input), walkFn); err != nil {
if err := WalkDir(DirFS("."), input, walkFn); err != nil {
return nil, nil, err
}
} else {
Expand Down Expand Up @@ -669,7 +648,7 @@ func openOutputFile(output string) (*os.File, error) {
if output == "" {
w = os.Stdout
} else {
if err := os.MkdirAll(path.Dir(output), 0777); err != nil {
if err := os.MkdirAll(filepath.Dir(output), 0777); err != nil {
return nil, err
}
err := try.Do(func(attempt int) (bool, error) {
Expand All @@ -690,7 +669,7 @@ func createSymlink(input, output string) error {
return err
}
}
if err := os.MkdirAll(path.Dir(output), 0777); err != nil {
if err := os.MkdirAll(filepath.Dir(output), 0777); err != nil {
return err
}
if err := os.Symlink(input, output); err != nil {
Expand Down Expand Up @@ -721,7 +700,7 @@ func minify(t Task) bool {
fileMimetype := mimetype
if mimetype == "" && !t.sync {
for _, src := range t.srcs {
ext := path.Ext(src)
ext := filepath.Ext(src)
if 0 < len(ext) {
ext = ext[1:]
}
Expand Down

0 comments on commit 5f59503

Please sign in to comment.