Skip to content

Commit 8a9197a

Browse files
authored
Merge pull request #7 from arduino/dos8.3fixes
Improved EquivalentTo() and added Canonical()
2 parents 9812a6a + ad24217 commit 8a9197a

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

paths.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -524,15 +524,22 @@ func (p *Path) EquivalentTo(other *Path) bool {
524524
if p.Clean().path == other.Clean().path {
525525
return true
526526
}
527-
absP, err := p.Abs()
528-
if err != nil {
529-
return false
527+
528+
if infoP, err := p.Stat(); err != nil {
529+
// go ahead with the next test...
530+
} else if infoOther, err := other.Stat(); err != nil {
531+
// go ahead with the next test...
532+
} else if os.SameFile(infoP, infoOther) {
533+
return true
530534
}
531-
absOther, err := other.Abs()
532-
if err != nil {
535+
536+
if absP, err := p.Abs(); err != nil {
537+
return false
538+
} else if absOther, err := other.Abs(); err != nil {
533539
return false
540+
} else {
541+
return absP.path == absOther.path
534542
}
535-
return absP.path == absOther.path
536543
}
537544

538545
// Parents returns all the parents directories of the current path. If the path is absolute
@@ -557,3 +564,18 @@ func (p *Path) Parents() []*Path {
557564
func (p *Path) String() string {
558565
return p.path
559566
}
567+
568+
// Canonical return a "canonical" Path for the given filename.
569+
// The meaning of "canonical" is OS-dependent but the goal of this method
570+
// is to always return the same path for a given file (factoring out all the
571+
// possibile ambiguities including, for example, relative paths traversal,
572+
// symlinks, drive volume letter case, etc).
573+
func (p *Path) Canonical() *Path {
574+
canonical := p.Clone()
575+
// https://github.com/golang/go/issues/17084#issuecomment-246645354
576+
canonical.FollowSymLink()
577+
if absPath, err := canonical.Abs(); err == nil {
578+
canonical = absPath
579+
}
580+
return canonical
581+
}

paths_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ package paths
3131

3232
import (
3333
"path/filepath"
34+
"runtime"
3435
"strings"
3536
"testing"
3637

@@ -311,6 +312,32 @@ func TestEquivalentPaths(t *testing.T) {
311312
require.True(t, New("file1", "abc").EquivalentTo(New("file1", "abc", "def", "..")))
312313
require.True(t, wd.Join("file1").EquivalentTo(New("file1")))
313314
require.True(t, wd.Join("file1").EquivalentTo(New("file1", "abc", "..")))
315+
316+
if runtime.GOOS == "windows" {
317+
q := New("_testdata", "anotherFile")
318+
r := New("_testdata", "ANOTHE~1")
319+
require.True(t, q.EquivalentTo(r))
320+
require.True(t, r.EquivalentTo(q))
321+
}
322+
}
323+
324+
func TestCanonicalize(t *testing.T) {
325+
wd, err := Getwd()
326+
require.NoError(t, err)
327+
328+
p := New("_testdata", "anotherFile").Canonical()
329+
require.Equal(t, wd.Join("_testdata", "anotherFile").String(), p.String())
330+
331+
p = New("_testdata", "nonexistentFile").Canonical()
332+
require.Equal(t, wd.Join("_testdata", "nonexistentFile").String(), p.String())
333+
334+
if runtime.GOOS == "windows" {
335+
q := New("_testdata", "ANOTHE~1").Canonical()
336+
require.Equal(t, wd.Join("_testdata", "anotherFile").String(), q.String())
337+
338+
r := New("c:\\").Canonical()
339+
require.Equal(t, "C:\\", r.String())
340+
}
314341
}
315342

316343
func TestRelativeTo(t *testing.T) {
@@ -341,6 +368,10 @@ func TestRelativeTo(t *testing.T) {
341368

342369
func TestWriteToTempFile(t *testing.T) {
343370
tmpDir := New("_testdata", "tmp")
371+
err := tmpDir.MkdirAll()
372+
require.NoError(t, err)
373+
defer tmpDir.RemoveAll()
374+
344375
tmpData := []byte("test")
345376
tmp, err := WriteToTempFile(tmpData, tmpDir, "prefix")
346377
defer tmp.Remove()

0 commit comments

Comments
 (0)