Skip to content

Commit 31be8d2

Browse files
committed
buffer: Resolve symlinks in file paths
Otherwise we can't identify if we have the same file open multiple times via different symlinks. The test must be adapted to resolve symlinks in `findBuffer()`.
1 parent e323cde commit 31be8d2

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

cmd/micro/micro_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/micro-editor/micro/v2/internal/buffer"
1212
"github.com/micro-editor/micro/v2/internal/config"
1313
"github.com/micro-editor/micro/v2/internal/screen"
14+
"github.com/micro-editor/micro/v2/internal/util"
1415
"github.com/micro-editor/tcell/v2"
1516
"github.com/stretchr/testify/assert"
1617
)
@@ -157,8 +158,9 @@ func openFile(file string) {
157158

158159
func findBuffer(file string) *buffer.Buffer {
159160
var buf *buffer.Buffer
161+
file = util.ResolvePath(file)
160162
for _, b := range buffer.OpenBuffers {
161-
if b.Path == file {
163+
if b.AbsPath == file {
162164
buf = b
163165
}
164166
}

internal/buffer/buffer.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ func NewBufferFromString(text, path string, btype BufType) *Buffer {
355355
// Places the cursor at startcursor. If startcursor is -1, -1 places the
356356
// cursor at an autodetected location (based on savecursor or :LINE:COL)
357357
func NewBuffer(r io.Reader, size int64, path string, btype BufType, cmd Command) *Buffer {
358-
absPath, err := filepath.Abs(path)
359-
if err != nil {
360-
absPath = path
358+
absPath := path
359+
if btype == BTDefault && path != "" {
360+
absPath = util.ResolvePath(path)
361361
}
362362

363363
b := new(Buffer)
@@ -391,6 +391,7 @@ func NewBuffer(r io.Reader, size int64, path string, btype BufType, cmd Command)
391391
}
392392
config.UpdatePathGlobLocals(b.Settings, absPath)
393393

394+
var err error
394395
b.encoding, err = htmlindex.Get(b.Settings["encoding"].(string))
395396
if err != nil {
396397
b.encoding = unicode.UTF8
@@ -489,7 +490,7 @@ func NewBuffer(r io.Reader, size int64, path string, btype BufType, cmd Command)
489490
}
490491
}
491492

492-
err = config.RunPluginFn("onBufferOpen", luar.New(ulua.L, b))
493+
err := config.RunPluginFn("onBufferOpen", luar.New(ulua.L, b))
493494
if err != nil {
494495
screen.TermMessage(err)
495496
}

internal/buffer/save.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,7 @@ func (b *Buffer) saveToFile(filename string, withSudo bool, autoSave bool) error
285285
return errors.New("Error: " + filename + " is not a regular file and cannot be saved")
286286
}
287287

288-
absFilename, err := filepath.Abs(filename)
289-
if err != nil {
290-
return err
291-
}
288+
absFilename := util.ResolvePath(filename)
292289

293290
// Get the leading path to the file | "." is returned if there's no leading path provided
294291
if dirname := filepath.Dir(absFilename); dirname != "." {

internal/util/util.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,38 @@ func DetermineEscapePath(dir string, path string) (string, string) {
489489
return url, ""
490490
}
491491

492+
// ResolvePath provides the absolute file path for the given relative file path
493+
// as well as resolves symlinks. If it fails to get the absolute path or to
494+
// resolve symlinks, it returns unresolved path in place of resolved one.
495+
func ResolvePath(path string) string {
496+
absPath, err := filepath.Abs(path)
497+
if err != nil {
498+
absPath = path
499+
}
500+
501+
var remainder []string
502+
for {
503+
resolvedPath, err := filepath.EvalSymlinks(absPath)
504+
if err == nil {
505+
absPath = resolvedPath
506+
break
507+
} else if errors.Is(err, fs.ErrNotExist) {
508+
remainder = append([]string{filepath.Base(absPath)}, remainder...)
509+
absPath = filepath.Dir(absPath)
510+
continue
511+
}
512+
break
513+
}
514+
515+
if len(remainder) > 0 {
516+
remainder = append([]string{absPath}, remainder...)
517+
absPath = filepath.Join(remainder...)
518+
absPath = filepath.Clean(absPath)
519+
}
520+
521+
return absPath
522+
}
523+
492524
// GetLeadingWhitespace returns the leading whitespace of the given byte array
493525
func GetLeadingWhitespace(b []byte) []byte {
494526
ws := []byte{}

0 commit comments

Comments
 (0)