Skip to content
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

HW8 is completed #12

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 73 additions & 4 deletions hw08_envdir_tool/env_reader.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,79 @@
package main

import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"strings"
"unicode"
)

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
// ReadDir reads a specified directory and returns map of env variables.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Обычно комментарий пишется перед объявлением функции и начинается с названия функции.

// Variables represented as files where filename is name of variable, file first line is a value.
env := make(Environment)
dataDir, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}

for _, d := range dataDir {
fileName := d.Name()

// skip recursive directory search and files with "="
if d.IsDir() || strings.Contains(fileName, "=") {
continue
}

filePath := filepath.Join(dir, fileName)
val, err := readFileValue(filePath)
// skip file with error
if err != nil {
continue
}
env[fileName] = val
}

return env, nil
}

func readFileValue(filePath string) (string, error) {
// function read file and return first "trail trimmed" string
r, err := os.Open(filePath)
if err != nil {
return "", err
}
defer r.Close()

st, err := r.Stat()
if err != nil {
return "", err
}

// don't read empty files
if st.Size() <= 0 {
return "", nil
}

bytes, err := ioutil.ReadAll(r)
if err != nil {
return "", err
}

// read only first line if it doesn't not empty
for _, val := range strings.Split(string(bytes), "\n") {
if val == "" {
continue
}

// convering 0x00 to \n magic
val = strings.ReplaceAll(val, string('\x00'), "\n")

return strings.TrimRightFunc(val, unicode.IsSpace), nil
}

return "", errors.New("empty result")
}
44 changes: 42 additions & 2 deletions hw08_envdir_tool/env_reader_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,47 @@
package main

import "testing"
import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/require"
)

func TestReadFileValue(t *testing.T) {
t.Run("not exist file", func(t *testing.T) {
_, err := readFileValue("testdata/env/not-exist")
require.True(t, os.IsNotExist(err))
})

t.Run("empty file", func(t *testing.T) {
val, err := readFileValue("testdata/env/UNSET")
require.Nil(t, err)
require.Equal(t, "", val)
})

t.Run("heavy variable", func(t *testing.T) {
sample := fmt.Sprintf(" foo\nwith new line")

val, err := readFileValue("testdata/env/FOO")
require.Nil(t, err)
require.Equal(t, sample, val)
})
}

func TestReadDir(t *testing.T) {
// Place your code here
t.Run("not exist dir", func(t *testing.T) {
_, err := ReadDir("testdata/env-not-exist")
err, ok := err.(*os.PathError)

require.True(t, ok)
require.NotNil(t, err)
})

t.Run("complex parse check", func(t *testing.T) {
envMap, err := ReadDir("testdata/env")
require.Nil(t, err)

require.Equal(t, envMap, Environment{"UNSET": "", "BAR": "bar", "HELLO": "\"hello\"", "FOO": " foo\nwith new line"})
})
}
37 changes: 34 additions & 3 deletions hw08_envdir_tool/executor.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
package main

// RunCmd runs a command + arguments (cmd) with environment variables from env
import (
"fmt"
"os/exec"
)

func RunCmd(cmd []string, env Environment) (returnCode int) {
// Place your code here
return
// RunCmd runs a command + arguments (cmd) with environment variables from env

execEnv := make([]string, len(env))
for envVariable, value := range env {
// skip empty values
if value == "" {
continue
}
execEnv = append(execEnv, fmt.Sprintf("%s=%s", envVariable, value))
}

command, args := cmd[0], cmd[1:]
cmdExec := exec.Command(command, args...)
cmdExec.Env = execEnv

stdoutStderr, err := cmdExec.CombinedOutput()
if err != nil {
exitError, ok := err.(*exec.ExitError)
if ok {
return exitError.ExitCode()
}

// os.PathError and other non caugth errors
return 1
}

fmt.Printf("%s", stdoutStderr)

return 0
}
28 changes: 26 additions & 2 deletions hw08_envdir_tool/executor_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
package main

import "testing"
import (
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/require"
)

func TestRunCmd(t *testing.T) {
// Place your code here
t.Run("not exist file", func(t *testing.T) {
exitCode := RunCmd([]string{"not-exist-command"}, nil)
require.EqualValues(t, 1, exitCode)
})

t.Run("check output", func(t *testing.T) {
r, w, err := os.Pipe()
require.Nil(t, err)

os.Stdout = w
exitCode := RunCmd([]string{"echo", "-n", "test"}, nil)
w.Close()

require.EqualValues(t, 0, exitCode)
out, err := ioutil.ReadAll(r)
require.Nil(t, err)

require.Equal(t, "test", string(out))
})
}
4 changes: 3 additions & 1 deletion hw08_envdir_tool/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/fixme_my_friend/hw08_envdir_tool
module github.com/ezhk/golang-learning/hw08_envdir_tool

go 1.14

require github.com/stretchr/testify v1.6.1
13 changes: 12 additions & 1 deletion hw08_envdir_tool/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
package main

import (
"os"
)

func main() {
// Place your code here
envDir, cmd := os.Args[1], os.Args[2:]
environment, err := ReadDir(envDir)
if err != nil {
os.Exit(1)
}

exitCode := RunCmd(cmd, environment)
os.Exit(exitCode)
}