mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
Support file modes in file system mock (#1716)
Support file mode in file system mock
This commit is contained in:
parent
f0babcade1
commit
d1130a11ac
@ -13,9 +13,14 @@ import (
|
||||
|
||||
var dirContent []byte
|
||||
|
||||
// FilesMock implements the functions from piperutils.Files with an in-memory file system.
|
||||
type fileProperties struct {
|
||||
content *[]byte
|
||||
mode *os.FileMode
|
||||
}
|
||||
|
||||
//FilesMock implements the functions from piperutils.Files with an in-memory file system.
|
||||
type FilesMock struct {
|
||||
files map[string]*[]byte
|
||||
files map[string]*fileProperties
|
||||
writtenFiles map[string]*[]byte
|
||||
removedFiles map[string]*[]byte
|
||||
currentDir string
|
||||
@ -24,7 +29,7 @@ type FilesMock struct {
|
||||
|
||||
func (f *FilesMock) init() {
|
||||
if f.files == nil {
|
||||
f.files = map[string]*[]byte{}
|
||||
f.files = map[string]*fileProperties{}
|
||||
}
|
||||
if f.removedFiles == nil {
|
||||
f.removedFiles = map[string]*[]byte{}
|
||||
@ -44,21 +49,39 @@ func (f *FilesMock) toAbsPath(path string) string {
|
||||
return path
|
||||
}
|
||||
|
||||
// AddFile establishes the existence of a virtual file.
|
||||
// AddFile establishes the existence of a virtual file. The file is
|
||||
// added with mode 644
|
||||
func (f *FilesMock) AddFile(path string, contents []byte) {
|
||||
f.associateContent(path, &contents)
|
||||
f.AddFileWithMode(path, contents, 0644)
|
||||
}
|
||||
|
||||
// AddDir establishes the existence of a virtual directory.
|
||||
// AddFileWithMode establishes the existence of a virtual file.
|
||||
func (f *FilesMock) AddFileWithMode(path string, contents []byte, mode os.FileMode) {
|
||||
f.associateContent(path, &contents, &mode)
|
||||
}
|
||||
|
||||
// AddDir establishes the existence of a virtual directory. The directory
|
||||
// is add with default mode 755
|
||||
func (f *FilesMock) AddDir(path string) {
|
||||
f.associateContent(path, &dirContent)
|
||||
f.AddDirWithMode(path, 0755)
|
||||
}
|
||||
|
||||
func (f *FilesMock) associateContent(path string, content *[]byte) {
|
||||
// AddDirWithMode establishes the existence of a virtual directory.
|
||||
func (f *FilesMock) AddDirWithMode(path string, mode os.FileMode) {
|
||||
f.associateContent(path, &dirContent, &mode)
|
||||
}
|
||||
|
||||
func (f *FilesMock) associateContent(path string, content *[]byte, mode *os.FileMode) {
|
||||
f.init()
|
||||
path = strings.ReplaceAll(path, "/", f.Separator)
|
||||
path = strings.ReplaceAll(path, "\\", f.Separator)
|
||||
f.files[f.toAbsPath(path)] = content
|
||||
path = f.toAbsPath(path)
|
||||
if _, ok := f.files[path]; !ok {
|
||||
f.files[path] = &fileProperties{}
|
||||
}
|
||||
props := f.files[path]
|
||||
props.content = content
|
||||
props.mode = mode
|
||||
}
|
||||
|
||||
// HasFile returns true if the virtual file system contains an entry for the given path.
|
||||
@ -87,20 +110,20 @@ func (f *FilesMock) FileExists(path string) (bool, error) {
|
||||
if f.files == nil {
|
||||
return false, nil
|
||||
}
|
||||
content, exists := f.files[f.toAbsPath(path)]
|
||||
props, exists := f.files[f.toAbsPath(path)]
|
||||
if !exists {
|
||||
return false, nil
|
||||
}
|
||||
return content != &dirContent, nil
|
||||
return props.content != &dirContent, nil
|
||||
}
|
||||
|
||||
// DirExists returns true, if the given path is a previously added directory, or a parent directory for any of the
|
||||
// previously added files.
|
||||
func (f *FilesMock) DirExists(path string) (bool, error) {
|
||||
path = f.toAbsPath(path)
|
||||
for entry, content := range f.files {
|
||||
for entry, props := range f.files {
|
||||
var dirComponents []string
|
||||
if content == &dirContent {
|
||||
if props.content == &dirContent {
|
||||
dirComponents = strings.Split(entry, f.Separator)
|
||||
} else {
|
||||
dirComponents = strings.Split(filepath.Dir(entry), f.Separator)
|
||||
@ -125,37 +148,37 @@ func (f *FilesMock) DirExists(path string) (bool, error) {
|
||||
// Copy checks if content has been associated with the given src path, and if so copies it under the given path dst.
|
||||
func (f *FilesMock) Copy(src, dst string) (int64, error) {
|
||||
f.init()
|
||||
content, exists := f.files[f.toAbsPath(src)]
|
||||
if !exists || content == &dirContent {
|
||||
props, exists := f.files[f.toAbsPath(src)]
|
||||
if !exists || props.content == &dirContent {
|
||||
return 0, fmt.Errorf("cannot copy '%s': %w", src, os.ErrNotExist)
|
||||
}
|
||||
f.AddFile(dst, *content)
|
||||
return int64(len(*content)), nil
|
||||
f.AddFileWithMode(dst, *props.content, *props.mode)
|
||||
return int64(len(*props.content)), nil
|
||||
}
|
||||
|
||||
// FileRead returns the content previously associated with the given path via AddFile(), or an error if no
|
||||
// content has been associated.
|
||||
func (f *FilesMock) FileRead(path string) ([]byte, error) {
|
||||
f.init()
|
||||
content, exists := f.files[f.toAbsPath(path)]
|
||||
props, exists := f.files[f.toAbsPath(path)]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("could not read '%s'", path)
|
||||
}
|
||||
// check if trying to open a directory for reading
|
||||
if content == &dirContent {
|
||||
if props.content == &dirContent {
|
||||
return nil, fmt.Errorf("could not read '%s': %w", path, os.ErrInvalid)
|
||||
}
|
||||
return *content, nil
|
||||
return *props.content, nil
|
||||
}
|
||||
|
||||
// FileWrite just forwards to AddFile(), i.e. the content is associated with the given path.
|
||||
func (f *FilesMock) FileWrite(path string, content []byte, _ os.FileMode) error {
|
||||
func (f *FilesMock) FileWrite(path string, content []byte, mode os.FileMode) error {
|
||||
f.init()
|
||||
// NOTE: FilesMock could be extended to have a set of paths for which FileWrite should fail.
|
||||
// This is why AddFile() exists separately, to differentiate the notion of setting up the mocking
|
||||
// versus implementing the methods from Files.
|
||||
f.writtenFiles[f.toAbsPath(path)] = &content
|
||||
f.AddFile(path, content)
|
||||
f.AddFileWithMode(path, content, mode)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -166,21 +189,21 @@ func (f *FilesMock) FileRemove(path string) error {
|
||||
return fmt.Errorf("the file '%s' does not exist: %w", path, os.ErrNotExist)
|
||||
}
|
||||
absPath := f.toAbsPath(path)
|
||||
content, exists := f.files[absPath]
|
||||
props, exists := f.files[absPath]
|
||||
if !exists {
|
||||
return fmt.Errorf("the file '%s' does not exist: %w", path, os.ErrNotExist)
|
||||
}
|
||||
delete(f.files, absPath)
|
||||
f.removedFiles[absPath] = content
|
||||
f.removedFiles[absPath] = props.content
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkdirAll creates a directory in the in-memory file system, so that this path is established to exist.
|
||||
func (f *FilesMock) MkdirAll(path string, _ os.FileMode) error {
|
||||
func (f *FilesMock) MkdirAll(path string, mode os.FileMode) error {
|
||||
// NOTE: FilesMock could be extended to have a set of paths for which MkdirAll should fail.
|
||||
// This is why AddDir() exists separately, to differentiate the notion of setting up the mocking
|
||||
// versus implementing the methods from Files.
|
||||
f.AddDir(path)
|
||||
f.AddDirWithMode(path, mode)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user