Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/cortesi/modd/conf"
"github.com/cortesi/modd/shell"
"github.com/cortesi/modd/utils"
"github.com/cortesi/modd/varcmd"
"github.com/cortesi/termlog"
)
Expand Down Expand Up @@ -123,7 +124,7 @@ func NewDaemonPen(block conf.Block, vars map[string]string, log termlog.TermLog)
if block.InDir != "" {
indir = block.InDir
} else {
indir, err = os.Getwd()
indir, err = utils.GetRealWd()
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions modd.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cortesi/modd/conf"
"github.com/cortesi/modd/notify"
"github.com/cortesi/modd/shell"
"github.com/cortesi/modd/utils"
"github.com/cortesi/moddwatch"
"github.com/cortesi/termlog"
)
Expand Down Expand Up @@ -108,7 +109,7 @@ func (mr *ModRunner) PrepOnly(initial bool) error {

func (mr *ModRunner) runBlock(b conf.Block, mod *moddwatch.Mod, dpen *DaemonPen) {
if b.InDir != "" {
currentDir, err := os.Getwd()
currentDir, err := utils.GetRealWd()
if err != nil {
mr.Log.Shout("Error getting current working directory: %s", err)
return
Expand Down Expand Up @@ -184,14 +185,14 @@ func (mr *ModRunner) runOnChan(modchan chan *moddwatch.Mod, readyCallback func()
ipatts = append(ipatts, filepath.Dir(mr.ConfPath))
}

currentDir, err := os.Getwd()
currentDir, err := utils.GetRealWd()
if err != nil {
return err
}

// FIXME: This takes a long time. We could start it in parallel with the
// first process run in a goroutine
watcher, err := moddwatch.Watch(currentDir, ipatts, []string{}, lullTime, modchan)

if err != nil {
return fmt.Errorf("Error watching: %s", err)
}
Expand Down
55 changes: 55 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package utils

import (
"os"
"path/filepath"
"strings"
"testing"
)

Expand Down Expand Up @@ -34,3 +36,56 @@ func WithTempDir(t *testing.T) func() {
}
}
}

// GetRealWd returns the current working directory with the path
// segments changed to the actual case on disk. Sticks to the
// logic of os.Getwd, without resolving symlinks.
func GetRealWd() (string, error) {
indir, err := os.Getwd()
if err != nil {
return "", err
}

// Initial stat to check if the os considers the file to exist.
// INFO: If we pass this point, the os considers this a path to an existing
// file. If we now find case discrepancies, we can assume that the
// filesystem is case-insensitive.
_, err = os.Stat(indir)
if err != nil {
return "", err
}

sepString := string(filepath.Separator)
prefix := filepath.VolumeName(indir) // empty on unix
relativePath := indir[len(prefix)+len(sepString):]

// Split the relative path into segments
segments := strings.Split(relativePath, sepString)
realPath := prefix + sepString

// Validate each segment
Seg:
for _, segment := range segments {
currentPath := filepath.Join(realPath, segment)
parentDir := filepath.Dir(currentPath)
if parentDir == "." {
parentDir = ""
}

entries, err := os.ReadDir(parentDir)
if err != nil {
return "", err
}

for _, entry := range entries {
if strings.EqualFold(entry.Name(), segment) {
realPath = filepath.Join(realPath, entry.Name())
continue Seg
}
}

return "", os.ErrNotExist
}

return realPath, nil
}