-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
avoid text file busy error on track #2494
base: main
Are you sure you want to change the base?
Changes from 7 commits
9119392
081f826
7430f84
9116cf8
7f33e6d
3751999
0ee6c95
5d340a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,7 +38,7 @@ func IsExecutable(filename string) bool { | |
return false | ||
} | ||
info, _ := os.Stat(filename) | ||
return info.Mode()&0x0100 != 0 | ||
return info.Mode()&0o0100 != 0 | ||
} | ||
|
||
// UserHomePath returns the absolute path of a file located in the user's home directory. | ||
|
@@ -77,6 +77,24 @@ func FileCopy(src string, dst string) error { | |
return os.WriteFile(dst, data, constants.WriteReadReadPerms) | ||
} | ||
|
||
// SetupExecFile copies a file into destination and set it to have exec perms, | ||
// if destination either does not exists, or is not executable | ||
func SetupExecFile(src string, dst string) error { | ||
if !IsExecutable(dst) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to error/log if the file isn't executable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want to error. This also happens on first install. |
||
// Either it was never installed, or it was partially done (copy or chmod | ||
// failure) | ||
// As the file is not executable, there is no risk of encountering text file busy | ||
// error during copy, because that happens when the binary is being executed. | ||
if err := FileCopy(src, dst); err != nil { | ||
return err | ||
} | ||
if err := os.Chmod(dst, constants.DefaultPerms755); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ReadFile reads a file and returns the contents as a string | ||
func ReadFile(filePath string) (string, error) { | ||
filePath = ExpandHome(filePath) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,9 @@ import ( | |
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/ava-labs/avalanche-cli/pkg/constants" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestExpandHome(t *testing.T) { | ||
|
@@ -45,29 +48,26 @@ func TestExpandHome(t *testing.T) { | |
} | ||
} | ||
|
||
// createTempGoMod creates a temporary go.mod file with the provided content. | ||
func createTempGoMod(t *testing.T, content string) string { | ||
// createTemp creates a temporary file with the provided name prefix and content. | ||
func createTemp(t *testing.T, namePrefix string, content string) string { | ||
t.Helper() | ||
file, err := os.CreateTemp("", "go.mod") | ||
file, err := os.CreateTemp("", namePrefix) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if _, err := file.Write([]byte(content)); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if err := file.Close(); err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
return file.Name() | ||
} | ||
|
||
// TestReadGoVersion tests all scenarios in one function using sub-tests. | ||
func TestReadGoVersion(t *testing.T) { | ||
t.Run("Success", func(t *testing.T) { | ||
tempFile := createTempGoMod(t, "module example.com/test\n\ngo 1.23\n") | ||
tempFile := createTemp(t, "go.mod", "module example.com/test\n\ngo 1.23\n") | ||
defer os.Remove(tempFile) // Clean up the temp file | ||
|
||
version, err := ReadGoVersion(tempFile) | ||
|
@@ -82,7 +82,7 @@ func TestReadGoVersion(t *testing.T) { | |
}) | ||
|
||
t.Run("NoVersion", func(t *testing.T) { | ||
tempFile := createTempGoMod(t, "module example.com/test\n") | ||
tempFile := createTemp(t, "go.mod", "module example.com/test\n") | ||
defer os.Remove(tempFile) | ||
|
||
_, err := ReadGoVersion(tempFile) | ||
|
@@ -98,3 +98,67 @@ func TestReadGoVersion(t *testing.T) { | |
} | ||
}) | ||
} | ||
|
||
func TestSetupExecFile(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love to see this test |
||
srcContent := "src content" | ||
destContent := "dest content" | ||
t.Run("Src does not exists", func(t *testing.T) { | ||
src := createTemp(t, "testexecfile", srcContent) | ||
dest := createTemp(t, "testexecfile", destContent) | ||
err := os.Remove(src) | ||
require.NoError(t, err) | ||
require.Equal(t, false, FileExists(src)) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, false, IsExecutable(dest)) | ||
err = SetupExecFile(src, dest) | ||
require.Error(t, err) | ||
content, err := os.ReadFile(dest) | ||
require.NoError(t, err) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, false, IsExecutable(dest)) | ||
require.Equal(t, destContent, string(content)) | ||
}) | ||
t.Run("Dest does not exists", func(t *testing.T) { | ||
src := createTemp(t, "testexecfile", srcContent) | ||
dest := createTemp(t, "testexecfile", destContent) | ||
err := os.Remove(dest) | ||
require.NoError(t, err) | ||
require.Equal(t, false, FileExists(dest)) | ||
require.Equal(t, false, IsExecutable(dest)) | ||
err = SetupExecFile(src, dest) | ||
require.NoError(t, err) | ||
content, err := os.ReadFile(dest) | ||
require.NoError(t, err) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, true, IsExecutable(dest)) | ||
require.Equal(t, srcContent, string(content)) | ||
}) | ||
t.Run("Dest is not executable", func(t *testing.T) { | ||
src := createTemp(t, "testexecfile", srcContent) | ||
dest := createTemp(t, "testexecfile", destContent) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, false, IsExecutable(dest)) | ||
err := SetupExecFile(src, dest) | ||
require.NoError(t, err) | ||
content, err := os.ReadFile(dest) | ||
require.NoError(t, err) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, true, IsExecutable(dest)) | ||
require.Equal(t, srcContent, string(content)) | ||
}) | ||
t.Run("Dest is already executable", func(t *testing.T) { | ||
src := createTemp(t, "testexecfile", srcContent) | ||
dest := createTemp(t, "testexecfile", destContent) | ||
err := os.Chmod(dest, constants.DefaultPerms755) | ||
require.NoError(t, err) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, true, IsExecutable(dest)) | ||
err = SetupExecFile(src, dest) | ||
require.NoError(t, err) | ||
content, err := os.ReadFile(dest) | ||
require.NoError(t, err) | ||
require.Equal(t, true, FileExists(dest)) | ||
require.Equal(t, true, IsExecutable(dest)) | ||
require.Equal(t, destContent, string(content)) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this &0o0100?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0o0100 (better 0o100, will fix), is a bit mask that, when applying bitwise AND (&) results
in a != 0 state whenever the file can be executed by the owner.
A perm can be seen as a 9-bit sequence mapping to rwxrwxrwx read-write-execute
for owner,group,everybody.
octal 0o100 means binary 001000000.
Probably better to set a constant and also add a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It previously was 0x0100 == binary 100000000. this was a bug, filtering in combinations where
the owner has read perms
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, would you mind adding a comment that explains this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added