From 7d3243d86fc0ddb6cb7455b3d94831ce7c2f3379 Mon Sep 17 00:00:00 2001 From: Cristian Cepeda <43882+pastuxso@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:13:50 -0500 Subject: [PATCH] Fixes runme when it attempts to access unreadable files or directories (#646) Handling the os.ErrPermission when an error occurs while trying to read files without proper permissions. Closes: #645 --------- Co-authored-by: Sebastian Tiedtke --- main_permissions_test.go | 60 ++++++++++++++++++++++++++++++++ pkg/project/project.go | 23 +++++++++--- testdata/permissions/basic.txtar | 32 +++++++++++++++++ 3 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 main_permissions_test.go create mode 100644 testdata/permissions/basic.txtar diff --git a/main_permissions_test.go b/main_permissions_test.go new file mode 100644 index 000000000..562840cba --- /dev/null +++ b/main_permissions_test.go @@ -0,0 +1,60 @@ +//go:build !windows + +package main + +import ( + "bufio" + "os" + "strings" + "testing" + + "github.com/rogpeppe/go-internal/testscript" +) + +func isDocker() bool { + if _, err := os.Stat("/.dockerenv"); err == nil { + return true + } + + paths := []string{"/proc/1/cgroup", "/proc/self/cgroup"} + for _, path := range paths { + file, err := os.Open(path) + if err != nil { + continue + } + + scanner := bufio.NewScanner(file) + isDocker := false + for scanner.Scan() { + if strings.Contains(scanner.Text(), "docker") || strings.Contains(scanner.Text(), "kubepods") { + isDocker = true + break + } + } + + if err := scanner.Err(); err != nil { + _ = file.Close() + return false + } + + _ = file.Close() + + if isDocker { + return true + } + } + + return false +} + +func TestRunmeFilePermissions(t *testing.T) { + if isDocker() { + t.Skip("Test skipped when running inside a Docker container") + return + } + + testscript.Run(t, testscript.Params{ + Dir: "testdata/permissions", + ContinueOnError: true, + }) +} diff --git a/pkg/project/project.go b/pkg/project/project.go index 5890e7b1d..95582327d 100644 --- a/pkg/project/project.go +++ b/pkg/project/project.go @@ -365,14 +365,22 @@ func (p *Project) loadFromDirectory( p.send(ctx, eventc, LoadEvent{Type: LoadEventStartedWalk}) err := util.Walk(p.fs, ".", func(path string, info fs.FileInfo, err error) error { - if err != nil { - return err - } - ignored := ignoreMatcher.Match( strings.Split(path, string(filepath.Separator)), info.IsDir(), ) + + switch err.(type) { + case nil: + case *os.PathError: + if !ignored { + p.logger.Warn("path error", zap.String("path", path), zap.Error(err)) + } + ignored = true + default: + return err + } + if !ignored { absPath := p.fs.Join(p.fs.Root(), path) @@ -454,7 +462,12 @@ func (p *Project) extractTasksFromFile( Data: LoadEventFinishedParsingDocumentData{Path: path}, }) - if err != nil { + switch err.(type) { + case nil: + case *os.PathError: + p.logger.Warn("path error", zap.String("path", path), zap.Error(err)) + return + default: p.send(ctx, eventc, LoadEvent{ Type: LoadEventError, Data: LoadEventErrorData{Err: err}, diff --git a/testdata/permissions/basic.txtar b/testdata/permissions/basic.txtar new file mode 100644 index 000000000..3a1024628 --- /dev/null +++ b/testdata/permissions/basic.txtar @@ -0,0 +1,32 @@ +exec chmod 000 secret +exec chmod 000 CONTRIBUTING.md +exec runme ls +cmp stdout output.txt +! stderr . + +-- secret/README.md -- + +```sh {"name":"secret-command"} +$ echo "This is a secret command" +``` + +-- CONTRIBUTING.md -- + +```sh {"name":"contributing-cell"} +$ echo "This is a secret command" +``` + +-- README.md -- + +```sh {"name":"command1"} +$ echo "Hello, runme 1!" +``` + +```sh {"name":"command2"} +$ echo "Hello, runme 2!" +``` + +-- output.txt -- +NAME FILE FIRST COMMAND DESCRIPTION NAMED +command1 README.md echo "Hello, runme 1!" Yes +command2 README.md echo "Hello, runme 2!" Yes