feat: use isatty to detect a Termios instead

Steve Moyer created

Change summary

commands/execenv/env.go         | 48 +++++++++++-----------------------
commands/execenv/env_test.go    | 20 +++++++-------
commands/execenv/env_testing.go |  6 +--
3 files changed, 28 insertions(+), 46 deletions(-)

Detailed changes

commands/execenv/env.go 🔗

@@ -6,6 +6,7 @@ import (
 	"io"
 	"os"
 
+	"github.com/mattn/go-isatty"
 	"github.com/spf13/cobra"
 	"github.com/vbauerster/mpb/v8"
 	"github.com/vbauerster/mpb/v8/decor"
@@ -20,46 +21,29 @@ const RootCommandName = "git-bug"
 
 const gitBugNamespace = "git-bug"
 
-type IOMode int
-
-const (
-	UnknownIOMode IOMode = iota
-	TerminalIOMode
-	PipedOrRedirectedIOMode
-)
-
-func getIOMode(io *os.File) IOMode {
-	info, err := io.Stat()
-	if err != nil {
-		panic("only os.StdIn or os.Stdout should be passed to this method")
-	}
-
-	if (info.Mode() & os.ModeCharDevice) == os.ModeCharDevice {
-		return TerminalIOMode
-	}
-
-	return PipedOrRedirectedIOMode
+func getIOMode(io *os.File) bool {
+	return !isatty.IsTerminal(io.Fd()) && !isatty.IsCygwinTerminal(io.Fd())
 }
 
 // Env is the environment of a command
 type Env struct {
-	Repo    repository.ClockedRepo
-	Backend *cache.RepoCache
-	In      io.Reader
-	InMode  IOMode
-	Out     Out
-	OutMode IOMode
-	Err     Out
+	Repo           repository.ClockedRepo
+	Backend        *cache.RepoCache
+	In             io.Reader
+	InRedirection  bool
+	Out            Out
+	OutRedirection bool
+	Err            Out
 }
 
 func NewEnv() *Env {
 	return &Env{
-		Repo:    nil,
-		In:      os.Stdin,
-		InMode:  getIOMode(os.Stdin),
-		Out:     out{Writer: os.Stdout},
-		OutMode: getIOMode(os.Stdout),
-		Err:     out{Writer: os.Stderr},
+		Repo:           nil,
+		In:             os.Stdin,
+		InRedirection:  getIOMode(os.Stdin),
+		Out:            out{Writer: os.Stdout},
+		OutRedirection: getIOMode(os.Stdout),
+		Err:            out{Writer: os.Stderr},
 	}
 }
 

commands/execenv/env_test.go 🔗

@@ -15,36 +15,36 @@ func TestGetIOMode(t *testing.T) {
 		name       string
 		in         *os.File
 		out        *os.File
-		expInMode  IOMode
-		expOutMode IOMode
+		expInMode  bool
+		expOutMode bool
 	}{
 		{
 			name:       "neither redirected",
 			in:         os.Stdin,
 			out:        os.Stdout,
-			expInMode:  TerminalIOMode,
-			expOutMode: TerminalIOMode,
+			expInMode:  false,
+			expOutMode: false,
 		},
 		{
 			name:       "in redirected",
 			in:         w,
 			out:        os.Stdout,
-			expInMode:  TerminalIOMode,
-			expOutMode: TerminalIOMode,
+			expInMode:  true,
+			expOutMode: false,
 		},
 		{
 			name:       "out redirected",
 			in:         os.Stdin,
 			out:        r,
-			expInMode:  TerminalIOMode,
-			expOutMode: TerminalIOMode,
+			expInMode:  false,
+			expOutMode: true,
 		},
 		{
 			name:       "both redirected",
 			in:         w,
 			out:        r,
-			expInMode:  PipedOrRedirectedIOMode,
-			expOutMode: PipedOrRedirectedIOMode,
+			expInMode:  true,
+			expOutMode: true,
 		},
 	}
 

commands/execenv/env_testing.go 🔗

@@ -49,8 +49,6 @@ func NewTestEnv(t *testing.T) *Env {
 
 	repo := repository.CreateGoGitTestRepo(t, false)
 
-	buf := new(bytes.Buffer)
-
 	backend, err := cache.NewRepoCacheNoEvents(repo)
 	require.NoError(t, err)
 
@@ -61,7 +59,7 @@ func NewTestEnv(t *testing.T) *Env {
 	return &Env{
 		Repo:    repo,
 		Backend: backend,
-		Out:     &TestOut{buf},
-		Err:     &TestOut{buf},
+		Out:     &TestOut{&bytes.Buffer{}},
+		Err:     &TestOut{&bytes.Buffer{}},
 	}
 }