Fix symlink behaviour (#1020)
* Fix symlink behaviour Make sure to evaluate symlinks when the path is not absolute and not local. Otherwise just fall back to regular absolute paths. Signed-off-by: Zoltán Reegn <zoltan.reegn@gmail.com>
This commit is contained in:
		
							parent
							
								
									ad258463b6
								
							
						
					
					
						commit
						4fb150238b
					
				|  | @ -34,6 +34,7 @@ type FileSystem struct { | ||||||
| 	Getwd             func() (string, error) | 	Getwd             func() (string, error) | ||||||
| 	Chdir             func(string) error | 	Chdir             func(string) error | ||||||
| 	Abs               func(string) (string, error) | 	Abs               func(string) (string, error) | ||||||
|  | 	EvalSymlinks      func(string) (string, error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func DefaultFileSystem() *FileSystem { | func DefaultFileSystem() *FileSystem { | ||||||
|  | @ -44,7 +45,7 @@ func DefaultFileSystem() *FileSystem { | ||||||
| 		Glob:         filepath.Glob, | 		Glob:         filepath.Glob, | ||||||
| 		Getwd:        os.Getwd, | 		Getwd:        os.Getwd, | ||||||
| 		Chdir:        os.Chdir, | 		Chdir:        os.Chdir, | ||||||
| 		Abs:        filepath.Abs, | 		EvalSymlinks: filepath.EvalSymlinks, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dfs.Stat = dfs.stat | 	dfs.Stat = dfs.stat | ||||||
|  | @ -52,6 +53,7 @@ func DefaultFileSystem() *FileSystem { | ||||||
| 	dfs.FileExistsAt = dfs.fileExistsAtDefault | 	dfs.FileExistsAt = dfs.fileExistsAtDefault | ||||||
| 	dfs.DirectoryExistsAt = dfs.directoryExistsDefault | 	dfs.DirectoryExistsAt = dfs.directoryExistsDefault | ||||||
| 	dfs.FileExists = dfs.fileExistsDefault | 	dfs.FileExists = dfs.fileExistsDefault | ||||||
|  | 	dfs.Abs = dfs.absDefault | ||||||
| 	return &dfs | 	return &dfs | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +93,9 @@ func FromFileSystem(params FileSystem) *FileSystem { | ||||||
| 	if params.Abs != nil { | 	if params.Abs != nil { | ||||||
| 		dfs.Abs = params.Abs | 		dfs.Abs = params.Abs | ||||||
| 	} | 	} | ||||||
| 
 | 	if params.EvalSymlinks != nil { | ||||||
|  | 		dfs.EvalSymlinks = params.EvalSymlinks | ||||||
|  | 	} | ||||||
| 	return dfs | 	return dfs | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -110,13 +114,20 @@ func (filesystem *FileSystem) readFile(name string) ([]byte, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (filesystem *FileSystem) fileExistsAtDefault(path string) bool { | func (filesystem *FileSystem) fileExistsAtDefault(path string) bool { | ||||||
|  | 	path, err := filesystem.resolveSymlinks(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
| 	fileInfo, err := filesystem.Stat(path) | 	fileInfo, err := filesystem.Stat(path) | ||||||
| 	return err == nil && fileInfo.Mode().IsRegular() | 	return err == nil && fileInfo.Mode().IsRegular() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (filesystem *FileSystem) fileExistsDefault(path string) (bool, error) { | func (filesystem *FileSystem) fileExistsDefault(path string) (bool, error) { | ||||||
| 	_, err := filesystem.Stat(path) | 	path, err := filesystem.resolveSymlinks(path) | ||||||
| 
 | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	_, err = filesystem.Stat(path) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if os.IsNotExist(err) { | 		if os.IsNotExist(err) { | ||||||
| 			return false, nil | 			return false, nil | ||||||
|  | @ -127,6 +138,38 @@ func (filesystem *FileSystem) fileExistsDefault(path string) (bool, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (filesystem *FileSystem) directoryExistsDefault(path string) bool { | func (filesystem *FileSystem) directoryExistsDefault(path string) bool { | ||||||
|  | 	path, err := filesystem.resolveSymlinks(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
| 	fileInfo, err := filesystem.Stat(path) | 	fileInfo, err := filesystem.Stat(path) | ||||||
| 	return err == nil && fileInfo.Mode().IsDir() | 	return err == nil && fileInfo.Mode().IsDir() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (filesystem *FileSystem) resolveSymlinks(path string) (string, error) { | ||||||
|  | 	if !filepath.IsAbs(path) && !filepath.IsLocal(path) { | ||||||
|  | 		basePath, err := filesystem.Getwd() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		basePath, err = filesystem.EvalSymlinks(basePath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		path, err := filesystem.EvalSymlinks(filepath.Join(basePath, path)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  | 		return path, nil | ||||||
|  | 	} | ||||||
|  | 	return path, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (filesystem *FileSystem) absDefault(path string) (string, error) { | ||||||
|  | 	path, err := filesystem.resolveSymlinks(path) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return filepath.Abs(path) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -12,28 +12,58 @@ import ( | ||||||
| func NewTestFileSystem() FileSystem { | func NewTestFileSystem() FileSystem { | ||||||
| 	replaceffs := FileSystem{ | 	replaceffs := FileSystem{ | ||||||
| 		Stat: func(s string) (os.FileInfo, error) { | 		Stat: func(s string) (os.FileInfo, error) { | ||||||
| 			if strings.HasPrefix(s, "existing_file") { | 			if strings.HasSuffix(s, "existing_file.txt") { | ||||||
| 				return fileStat{mode: 0}, nil | 				return fileStat{mode: 0}, nil | ||||||
| 			} | 			} | ||||||
| 			if strings.HasPrefix(s, "existing_dir") { | 			if strings.HasSuffix(s, "existing_dir") { | ||||||
| 				return fileStat{mode: fs.ModeDir}, nil | 				return fileStat{mode: fs.ModeDir}, nil | ||||||
| 			} | 			} | ||||||
| 			return nil, errors.New("Error") | 			return nil, errors.New("Error") | ||||||
| 		}, | 		}, | ||||||
|  | 		Getwd: func() (string, error) { | ||||||
|  | 			return "/test/dir", nil | ||||||
|  | 		}, | ||||||
|  | 		EvalSymlinks: func(s string) (string, error) { | ||||||
|  | 			if s == "/test/dir" { | ||||||
|  | 				return "/real/dir", nil | ||||||
|  | 			} else { | ||||||
|  | 				return s, nil | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 	return *FromFileSystem(replaceffs) | 	return *FromFileSystem(replaceffs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestFs_resolveSymlinks(t *testing.T) { | ||||||
|  | 	ffs := NewTestFileSystem() | ||||||
|  | 	path, _ := ffs.resolveSymlinks("../existing_file.txt") | ||||||
|  | 	if path != "/real/existing_file.txt" { | ||||||
|  | 		t.Errorf("Expected absolute path %s but got %s", "/real/existing_file.txt", path) | ||||||
|  | 	} | ||||||
|  | 	path, _ = ffs.resolveSymlinks("./existing_file.txt") | ||||||
|  | 	if path != "./existing_file.txt" { | ||||||
|  | 		t.Errorf("Expected local path %s but got %s", "./existing_file.txt", path) | ||||||
|  | 	} | ||||||
|  | 	path, _ = ffs.resolveSymlinks("existing_file.txt") | ||||||
|  | 	if path != "existing_file.txt" { | ||||||
|  | 		t.Errorf("Expected local path %s but got %s", "existing_file.txt", path) | ||||||
|  | 	} | ||||||
|  | 	path, _ = ffs.resolveSymlinks("/a/b/c/existing_file.txt") | ||||||
|  | 	if path != "/a/b/c/existing_file.txt" { | ||||||
|  | 		t.Errorf("Expected absolute path %s but got %s", "/a/b/c/existing_file.txt", path) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestFs_fileExistsDefault(t *testing.T) { | func TestFs_fileExistsDefault(t *testing.T) { | ||||||
| 	ffs := NewTestFileSystem() | 	ffs := NewTestFileSystem() | ||||||
| 	var exists, _ = ffs.FileExists("existing_file.txt") | 	exists, _ := ffs.FileExists("existing_file.txt") | ||||||
| 	if !exists { | 	if !exists { | ||||||
| 		t.Errorf("Expected file %s, not found", "existing_file.txt") | 		t.Errorf("Expected file %s, not found", "existing_file.txt") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	exists, _ = ffs.FileExists("non_existing_file.txt") | 	exists, _ = ffs.FileExists("missing_file.txt") | ||||||
| 	if exists { | 	if exists { | ||||||
| 		t.Errorf("Not expected file %s, found", "non_existing_file.txt") | 		t.Errorf("Not expected file %s, found", "missing_file.txt") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	dfs := DefaultFileSystem() | 	dfs := DefaultFileSystem() | ||||||
|  | @ -46,14 +76,14 @@ func TestFs_fileExistsDefault(t *testing.T) { | ||||||
| func TestFs_fileExistsAtDefault(t *testing.T) { | func TestFs_fileExistsAtDefault(t *testing.T) { | ||||||
| 	ffs := NewTestFileSystem() | 	ffs := NewTestFileSystem() | ||||||
| 
 | 
 | ||||||
| 	var exists = ffs.FileExistsAt("existing_file.txt") | 	exists := ffs.FileExistsAt("existing_file.txt") | ||||||
| 	if !exists { | 	if !exists { | ||||||
| 		t.Errorf("Expected file %s, not found", "existing_file.txt") | 		t.Errorf("Expected file %s, not found", "existing_file.txt") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	exists = ffs.FileExistsAt("non_existing_file.txt") | 	exists = ffs.FileExistsAt("missing_file.txt") | ||||||
| 	if exists { | 	if exists { | ||||||
| 		t.Errorf("Not expected file %s, found", "non_existing_file.txt") | 		t.Errorf("Not expected file %s, found", "missing_file.txt") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	exists = ffs.FileExistsAt("existing_dir") | 	exists = ffs.FileExistsAt("existing_dir") | ||||||
|  | @ -70,12 +100,12 @@ func TestFs_fileExistsAtDefault(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| func TestFs_directoryExistsDefault(t *testing.T) { | func TestFs_directoryExistsDefault(t *testing.T) { | ||||||
| 	ffs := NewTestFileSystem() | 	ffs := NewTestFileSystem() | ||||||
| 	var exists = ffs.DirectoryExistsAt("existing_dir") | 	exists := ffs.DirectoryExistsAt("existing_dir") | ||||||
| 	if !exists { | 	if !exists { | ||||||
| 		t.Errorf("Expected file %s, not found", "existing_dir") | 		t.Errorf("Expected file %s, not found", "existing_dir") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	exists = ffs.DirectoryExistsAt("not_existing_dir") | 	exists = ffs.DirectoryExistsAt("missing_dir") | ||||||
| 	if exists { | 	if exists { | ||||||
| 		t.Errorf("Not expected file %s, found", "existing_dir") | 		t.Errorf("Not expected file %s, found", "existing_dir") | ||||||
| 	} | 	} | ||||||
|  | @ -148,7 +178,8 @@ func TestFs_DefaultBuilder(t *testing.T) { | ||||||
| 		ffs.Stat == nil || | 		ffs.Stat == nil || | ||||||
| 		ffs.Getwd == nil || | 		ffs.Getwd == nil || | ||||||
| 		ffs.Chdir == nil || | 		ffs.Chdir == nil || | ||||||
| 		ffs.Abs == nil { | 		ffs.Abs == nil || | ||||||
|  | 		ffs.EvalSymlinks == nil { | ||||||
| 		t.Errorf("Missing functions in DefaultFileSystem") | 		t.Errorf("Missing functions in DefaultFileSystem") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue