[Fix] Attempt to resolve symbolic links. Resolves #13 .

This commit is contained in:
Thomas M. Edwards 2020-05-19 06:55:57 -05:00
parent 1167b5ef83
commit e082e597f3

View file

@ -13,6 +13,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
// external packages // external packages
"github.com/radovskyb/watcher" "github.com/radovskyb/watcher"
) )
@ -21,14 +22,18 @@ var programDir string
var workingDir string var workingDir string
func init() { func init() {
// Attempt to get the program directory, failure is okay. // Attempt to get the canonical program directory, failure is okay.
if pp, err := os.Executable(); err == nil { if pp, err := os.Executable(); err == nil {
programDir = filepath.Dir(pp) if pd, err := filepath.EvalSymlinks(filepath.Dir(pp)); err == nil {
programDir = pd
}
} }
// Attempt to get the working directory, failure is okay. // Attempt to get the canonical working directory, failure is okay.
if wd, err := os.Getwd(); err == nil { if wd, err := os.Getwd(); err == nil {
workingDir = wd if wd, err := filepath.EvalSymlinks(wd); err == nil {
workingDir = wd
}
} }
} }
@ -49,28 +54,40 @@ func getFilenames(pathnames []string, outFilename string) []string {
return nil return nil
} }
absolute, err := filepath.Abs(path) // Get the absolute path.
absolute, err := absPath(path)
if err != nil { if err != nil {
return err return err
} }
// The output file must not be one of the input files.
if absolute == absOutFile { if absolute == absOutFile {
return errNoOutToIn return errNoOutToIn
} }
relative, _ := filepath.Rel(workingDir, absolute) // Failure is okay.
if relative != "" { // Return a relative path if one can be resolved and it is shorter than the
filenames = append(filenames, relative) // absolute path, failure is okay.
} else { if relative, err := filepath.Rel(workingDir, absolute); err == nil {
filenames = append(filenames, absolute) if relative, err := filepath.EvalSymlinks(relative); err == nil {
if len(relative) < len(absolute) {
filenames = append(filenames, relative)
return nil
}
}
} }
filenames = append(filenames, absolute)
return nil return nil
} }
// Get the absolute output filename. // Get the absolute output filename.
absOutFile, err := filepath.Abs(outFilename) if abs, err := absPath(outFilename); err == nil {
if err != nil { absOutFile = abs
} else {
log.Fatalf("error: path %s: %s", outFilename, err.Error()) log.Fatalf("error: path %s: %s", outFilename, err.Error())
} }
// Walk the pathnames.
for _, pathname := range pathnames { for _, pathname := range pathnames {
if pathname == "-" { if pathname == "-" {
log.Print("warning: path -: Reading from standard input is unsupported.") log.Print("warning: path -: Reading from standard input is unsupported.")
@ -179,20 +196,45 @@ func watchFilesystem(pathnames []string, outFilename string, buildCallback func(
} }
} }
func absPath(original string) (string, error) {
var absolute string
if abs, err := filepath.Abs(original); err == nil {
absolute = abs
if abs, err := filepath.EvalSymlinks(absolute); err == nil {
absolute = abs
} else {
dir, base := filepath.Split(absolute)
if abs, err := filepath.EvalSymlinks(dir); err == nil {
absolute = filepath.Join(abs, base)
} else {
return "", err
}
}
} else {
return "", err
}
return absolute, nil
}
func relPath(original string) string { func relPath(original string) string {
absolute, err := filepath.Abs(original) absolute, err := absPath(original)
if err != nil { if err != nil {
// Failure is okay, just return the original path. // Failure is okay, just return the original path.
return original return original
} }
relative, err := filepath.Rel(workingDir, absolute) if relative, err := filepath.Rel(workingDir, absolute); err == nil {
if err != nil { if relative, err := filepath.EvalSymlinks(relative); err == nil {
// Failure is okay, just return the absolute path. if len(relative) < len(absolute) {
return absolute return relative
}
}
} }
return relative // Failure is okay, just return the absolute path.
return absolute
} }
func knownFileType(filename string) bool { func knownFileType(filename string) bool {