diff --git a/.golangci.yml b/.golangci.yml index 85eb8d5..b9f4356 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -14,3 +14,4 @@ linters: - nakedret - wsl - gofumpt + - gosec diff --git a/hw08_envdir_tool/env_reader.go b/hw08_envdir_tool/env_reader.go index 1a1f12d..4fadd53 100644 --- a/hw08_envdir_tool/env_reader.go +++ b/hw08_envdir_tool/env_reader.go @@ -1,10 +1,61 @@ package main +import ( + "bufio" + "io" + "io/ioutil" + "os" + "strings" +) + type Environment map[string]string // ReadDir reads a specified directory and returns map of env variables. // Variables represented as files where filename is name of variable, file first line is a value. func ReadDir(dir string) (Environment, error) { - // Place your code here - return nil, nil + e := make(map[string]string) + files, err := ioutil.ReadDir(dir) + if err != nil { + return e, err + } + for _, file := range files { + if !file.IsDir() && file.Mode().IsRegular() { + val, err := ReadFile(dir + "/" + file.Name()) + if err != nil { + return nil, err + } + key := file.Name() + if !strings.Contains(key, `=`) && !strings.Contains(key, `;`) { + e[key] = ExtractEnv(val) + } + } + } + + return e, nil +} + +func ReadFile(filePath string) (string, error) { + f, err := os.Open(filePath) + defer func() { + if err := f.Close(); err != nil { + return + } + }() + if err != nil { + return "", err + } + reader := bufio.NewReader(f) + b, _, err := reader.ReadLine() + if err != nil && err != io.EOF { + return "", err + } + + return string(b), nil +} + +func ExtractEnv(text string) string { + text = strings.TrimRight(text, " ") + text = strings.Replace(text, "\x00", "\n", -1) + + return text } diff --git a/hw08_envdir_tool/env_reader_test.go b/hw08_envdir_tool/env_reader_test.go index 7962c06..bf08849 100644 --- a/hw08_envdir_tool/env_reader_test.go +++ b/hw08_envdir_tool/env_reader_test.go @@ -1,7 +1,88 @@ package main -import "testing" +import ( + "github.com/stretchr/testify/require" + "os" + "testing" +) func TestReadDir(t *testing.T) { - // Place your code here + t.Run("Нет файлов в директории", func(t *testing.T) { + os.RemoveAll("testdata/env/no") + if err := os.Mkdir("testdata/env/no", os.ModePerm); err != nil { + return + } + env, err := ReadDir("testdata/env/no") + require.Equal(t, env, Environment{}) + require.NoError(t, err) + os.RemoveAll("testdata/env/no") + }) + + t.Run("Проверка = и ; в именах", func(t *testing.T) { + if err := os.RemoveAll("testdata/env/no"); err != nil { + return + } + if err := os.Mkdir("testdata/env/no", os.ModePerm); err != nil { + return + } + f1, err := os.Create("testdata/env/no/TES=T1") + if err != nil { + return + } + f2, err := os.Create("testdata/env/no/TES;T2") + if err != nil { + return + } + env, err := ReadDir("testdata/env/no") + if err != nil { + return + } + require.Equal(t, env, Environment{}) + require.NoError(t, err) + if err = f1.Close(); err != nil { + return + } + if err = f2.Close(); err != nil { + return + } + if err = os.RemoveAll("testdata/env/no"); err != nil { + return + } + }) +} + +func TestReadFile(t *testing.T) { + t.Run("Файл не существует", func(t *testing.T) { + str, err := ReadFile("dsvfsdfdfdv") + require.Equal(t, str, "") + require.Error(t, err) + }) + t.Run("Файл пуст", func(t *testing.T) { + str, err := ReadFile("testdata/env/UNSET") + require.Equal(t, str, "") + require.NoError(t, err) + }) +} + +func TestExtractEnv(t *testing.T) { + + t.Run("Zero escaping", func(t *testing.T) { + require.Equal(t, "zero_escape\nwith new line", ExtractEnv("zero_escape\x00with new line")) + }) + + t.Run("Quotes", func(t *testing.T) { + require.Equal(t, `"quotes"`, ExtractEnv("\"quotes\"")) + }) + + t.Run("Pre spacing", func(t *testing.T) { + require.Equal(t, " pre_spased", ExtractEnv(" pre_spased")) + }) + + t.Run("Post spacing", func(t *testing.T) { + require.Equal(t, "post_spased", ExtractEnv("post_spased ")) + }) + + t.Run("Multy spacing", func(t *testing.T) { + require.Equal(t, " multy spased", ExtractEnv(" multy spased ")) + }) } diff --git a/hw08_envdir_tool/executor.go b/hw08_envdir_tool/executor.go index f01d6be..998cb99 100644 --- a/hw08_envdir_tool/executor.go +++ b/hw08_envdir_tool/executor.go @@ -1,7 +1,34 @@ package main -// RunCmd runs a command + arguments (cmd) with environment variables from env +import ( + "os" + "os/exec" +) + func RunCmd(cmd []string, env Environment) (returnCode int) { - // Place your code here - return + c := exec.Command(cmd[0], cmd[1:]...) + for k, v := range env { + _, ok := os.LookupEnv(k) + if ok { + if err := os.Unsetenv(k); err != nil { + return -1 + } + } + if v != "" { + if err := os.Setenv(k, v); err != nil { + return -1 + } + } + } + c.Stdout = os.Stdout + c.Stderr = os.Stderr + if err := c.Run(); err != nil { + if code, ok := err.(*exec.ExitError); ok { + return code.ExitCode() + } + + return -1 + } + + return 0 } diff --git a/hw08_envdir_tool/executor_test.go b/hw08_envdir_tool/executor_test.go index 6402ce3..233736e 100644 --- a/hw08_envdir_tool/executor_test.go +++ b/hw08_envdir_tool/executor_test.go @@ -1,7 +1,17 @@ package main -import "testing" +import ( + "github.com/stretchr/testify/require" + "testing" +) func TestRunCmd(t *testing.T) { - // Place your code here + t.Run("Команда не существует", func(t *testing.T) { + code := RunCmd([]string{"sffdsfsvs"}, Environment{"E1": "val1"}) + require.Equal(t, code, -1) + }) + t.Run("Команда выполнилась", func(t *testing.T) { + code := RunCmd([]string{"ls"}, Environment{"E1": "val1"}) + require.Equal(t, code, 0) + }) } diff --git a/hw08_envdir_tool/go.mod b/hw08_envdir_tool/go.mod index 8536af6..4008bb9 100644 --- a/hw08_envdir_tool/go.mod +++ b/hw08_envdir_tool/go.mod @@ -1,3 +1,5 @@ -module github.com/fixme_my_friend/hw08_envdir_tool +module github.com/tiburon-777/HW_OTUS/hw08_envdir_tool go 1.14 + +require github.com/stretchr/testify v1.6.1 diff --git a/hw08_envdir_tool/main.go b/hw08_envdir_tool/main.go index 441440a..dff44ae 100644 --- a/hw08_envdir_tool/main.go +++ b/hw08_envdir_tool/main.go @@ -1,5 +1,13 @@ package main +import "os" + func main() { - // Place your code here + // парсим аргументы + args := os.Args + env, err := ReadDir(args[1]) + if err != nil { + os.Exit(111) + } + os.Exit(RunCmd(args[2:], env)) }