golang 1.14 doesn't like calling NewFile on existing files. Port solution over from Terraform

This commit is contained in:
Megan Marsh 2020-04-09 14:38:17 -07:00
parent 73c349d09c
commit 217dcbb97f
8 changed files with 143 additions and 113 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/chzyer/readline"
"github.com/hashicorp/packer/helper/wrappedreadline"
"github.com/hashicorp/packer/helper/wrappedstreams"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template"
"github.com/hashicorp/packer/template/interpolate"
@ -115,7 +116,7 @@ func (*ConsoleCommand) AutocompleteFlags() complete.Flags {
func (c *ConsoleCommand) modePiped(session *REPLSession) int {
var lastResult string
scanner := bufio.NewScanner(wrappedreadline.Stdin())
scanner := bufio.NewScanner(wrappedstreams.Stdin())
for scanner.Scan() {
result, err := session.Handle(strings.TrimSpace(scanner.Text()))
if err != nil {

View File

@ -9,7 +9,7 @@ import (
kvflag "github.com/hashicorp/packer/helper/flag-kv"
sliceflag "github.com/hashicorp/packer/helper/flag-slice"
"github.com/hashicorp/packer/helper/wrappedreadline"
"github.com/hashicorp/packer/helper/wrappedstreams"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template"
)
@ -166,7 +166,7 @@ func (m *Meta) ValidateFlags() error {
// StdinPiped returns true if the input is piped.
func (m *Meta) StdinPiped() bool {
fi, err := wrappedreadline.Stdin().Stat()
fi, err := wrappedstreams.Stdin().Stat()
if err != nil {
// If there is an error, let's just say its not piped
return false

View File

@ -1,5 +1,7 @@
// Shamelessly copied from the Terraform repo because it wasn't worth vendoring
// out two hundred lines of code so Packer could use it too.
// STOLEN SHAMELESSLY FROM THE TERRAFORM REPO BECAUSE VENDORING OUT
// WRAPPEDREADLINE AND WRAPPEDSTREAMS FELT LIKE TOO MUCH WORK.
//
// "a little copying is better than a lot of dependency"
//
// wrappedreadline is a package that has helpers for interacting with
// readline from a panicwrap executable.
@ -13,24 +15,24 @@
package wrappedreadline
import (
"os"
"runtime"
"github.com/chzyer/readline"
"github.com/mitchellh/panicwrap"
"github.com/hashicorp/packer/helper/wrappedstreams"
)
// Override overrides the values in readline.Config that need to be
// set with wrapped values.
func Override(cfg *readline.Config) *readline.Config {
cfg.Stdin = Stdin()
cfg.Stdout = Stdout()
cfg.Stderr = Stderr()
cfg.Stdin = wrappedstreams.Stdin()
cfg.Stdout = wrappedstreams.Stdout()
cfg.Stderr = wrappedstreams.Stderr()
cfg.FuncGetWidth = TerminalWidth
cfg.FuncIsTerminal = IsTerminal
rm := RawMode{StdinFd: int(Stdin().Fd())}
rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
cfg.FuncMakeRaw = rm.Enter
cfg.FuncExitRaw = rm.Exit
@ -45,9 +47,9 @@ func IsTerminal() bool {
}
// Same implementation as readline but with our custom fds
return readline.IsTerminal(int(Stdin().Fd())) &&
(readline.IsTerminal(int(Stdout().Fd())) ||
readline.IsTerminal(int(Stderr().Fd())))
return readline.IsTerminal(int(wrappedstreams.Stdin().Fd())) &&
(readline.IsTerminal(int(wrappedstreams.Stdout().Fd())) ||
readline.IsTerminal(int(wrappedstreams.Stderr().Fd())))
}
// TerminalWidth gets the terminal width in characters.
@ -78,43 +80,3 @@ func (r *RawMode) Exit() error {
return readline.Restore(r.StdinFd, r.state)
}
// Package provides access to the standard OS streams
// (stdin, stdout, stderr) even if wrapped under panicwrap.
// Stdin returns the true stdin of the process.
func Stdin() *os.File {
stdin := os.Stdin
if panicwrap.Wrapped(nil) {
stdin = wrappedStdin
}
return stdin
}
// Stdout returns the true stdout of the process.
func Stdout() *os.File {
stdout := os.Stdout
if panicwrap.Wrapped(nil) {
stdout = wrappedStdout
}
return stdout
}
// Stderr returns the true stderr of the process.
func Stderr() *os.File {
stderr := os.Stderr
if panicwrap.Wrapped(nil) {
stderr = wrappedStderr
}
return stderr
}
// These are the wrapped standard streams. These are setup by the
// platform specific code in initPlatform.
var (
wrappedStdin *os.File
wrappedStdout *os.File
wrappedStderr *os.File
)

View File

@ -3,15 +3,16 @@
package wrappedreadline
import (
"os"
"syscall"
"unsafe"
"github.com/hashicorp/packer/helper/wrappedstreams"
)
// getWidth impl for Unix
func getWidth() int {
stdoutFd := int(Stdout().Fd())
stderrFd := int(Stderr().Fd())
stdoutFd := int(wrappedstreams.Stdout().Fd())
stderrFd := int(wrappedstreams.Stderr().Fd())
w := getWidthFd(stdoutFd)
if w < 0 {
@ -43,10 +44,3 @@ func getWidthFd(stdoutFd int) int {
return int(ws.Col)
}
func init() {
// The standard streams are passed in via extra file descriptors.
wrappedStdin = os.NewFile(uintptr(3), "stdin")
wrappedStdout = os.NewFile(uintptr(4), "stdout")
wrappedStderr = os.NewFile(uintptr(5), "stderr")
}

View File

@ -2,56 +2,7 @@
package wrappedreadline
import (
"log"
"os"
"syscall"
)
// getWidth impl for other
func getWidth() int {
return 0
}
func init() {
wrappedStdin = openConsole("CONIN$", os.Stdin)
wrappedStdout = openConsole("CONOUT$", os.Stdout)
wrappedStderr = wrappedStdout
}
// openConsole opens a console handle, using a backup if it fails.
// This is used to get the exact console handle instead of the redirected
// handles from panicwrap.
func openConsole(name string, backup *os.File) *os.File {
// Convert to UTF16
path, err := syscall.UTF16PtrFromString(name)
if err != nil {
log.Printf("[ERROR] wrappedstreams: %s", err)
return backup
}
// Determine the share mode
var shareMode uint32
switch name {
case "CONIN$":
shareMode = syscall.FILE_SHARE_READ
case "CONOUT$":
shareMode = syscall.FILE_SHARE_WRITE
}
// Get the file
h, err := syscall.CreateFile(
path,
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
shareMode,
nil,
syscall.OPEN_EXISTING,
0, 0)
if err != nil {
log.Printf("[ERROR] wrappedstreams: %s", err)
return backup
}
// Create the Go file
return os.NewFile(uintptr(h), name)
}

View File

@ -0,0 +1,49 @@
// STOLEN SHAMELESSLY FROM THE TERRAFORM REPO BECAUSE VENDORING OUT
// WRAPPEDREADLINE AND WRAPPEDSTREAMS FELT LIKE TOO MUCH WORK.
//
// "a little copying is better than a lot of dependency"
//
// Package wrappedstreams provides access to the standard OS streams
// (stdin, stdout, stderr) even if wrapped under panicwrap.
package wrappedstreams
import (
"os"
"github.com/mitchellh/panicwrap"
)
// Stdin returns the true stdin of the process.
func Stdin() *os.File {
stdin, _, _ := fds()
return stdin
}
// Stdout returns the true stdout of the process.
func Stdout() *os.File {
_, stdout, _ := fds()
return stdout
}
// Stderr returns the true stderr of the process.
func Stderr() *os.File {
_, _, stderr := fds()
return stderr
}
func fds() (stdin, stdout, stderr *os.File) {
stdin, stdout, stderr = os.Stdin, os.Stdout, os.Stderr
if panicwrap.Wrapped(nil) {
initPlatform()
stdin, stdout, stderr = wrappedStdin, wrappedStdout, wrappedStderr
}
return
}
// These are the wrapped standard streams. These are setup by the
// platform specific code in initPlatform.
var (
wrappedStdin *os.File
wrappedStdout *os.File
wrappedStderr *os.File
)

View File

@ -0,0 +1,21 @@
// +build !windows
package wrappedstreams
import (
"os"
"sync"
)
var initOnce sync.Once
func initPlatform() {
// These must be initialized lazily, once it's been determined that this is
// a wrapped process.
initOnce.Do(func() {
// The standard streams are passed in via extra file descriptors.
wrappedStdin = os.NewFile(uintptr(3), "stdin")
wrappedStdout = os.NewFile(uintptr(4), "stdout")
wrappedStderr = os.NewFile(uintptr(5), "stderr")
})
}

View File

@ -0,0 +1,52 @@
// +build windows
package wrappedstreams
import (
"log"
"os"
"syscall"
)
func initPlatform() {
wrappedStdin = openConsole("CONIN$", os.Stdin)
wrappedStdout = openConsole("CONOUT$", os.Stdout)
wrappedStderr = wrappedStdout
}
// openConsole opens a console handle, using a backup if it fails.
// This is used to get the exact console handle instead of the redirected
// handles from panicwrap.
func openConsole(name string, backup *os.File) *os.File {
// Convert to UTF16
path, err := syscall.UTF16PtrFromString(name)
if err != nil {
log.Printf("[ERROR] wrappedstreams: %s", err)
return backup
}
// Determine the share mode
var shareMode uint32
switch name {
case "CONIN$":
shareMode = syscall.FILE_SHARE_READ
case "CONOUT$":
shareMode = syscall.FILE_SHARE_WRITE
}
// Get the file
h, err := syscall.CreateFile(
path,
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
shareMode,
nil,
syscall.OPEN_EXISTING,
0, 0)
if err != nil {
log.Printf("[ERROR] wrappedstreams: %s", err)
return backup
}
// Create the Go file
return os.NewFile(uintptr(h), name)
}