mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-09 00:32:09 -04:00
* Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at https://hashi.co/license-faq, and details of the license at www.hashicorp.com/bsl. * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package shell
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
// UnixReader is a Reader implementation that automatically converts
|
|
// Windows line endings to Unix line endings.
|
|
type UnixReader struct {
|
|
Reader io.Reader
|
|
|
|
buf []byte
|
|
once sync.Once
|
|
scanner *bufio.Scanner
|
|
}
|
|
|
|
func (r *UnixReader) Read(p []byte) (n int, err error) {
|
|
// Create the buffered reader once
|
|
r.once.Do(func() {
|
|
r.scanner = bufio.NewScanner(r.Reader)
|
|
r.scanner.Split(scanUnixLine)
|
|
})
|
|
|
|
// If we have no data in our buffer, scan to the next token
|
|
if len(r.buf) == 0 {
|
|
if !r.scanner.Scan() {
|
|
err = r.scanner.Err()
|
|
if err == nil {
|
|
err = io.EOF
|
|
}
|
|
|
|
return 0, err
|
|
}
|
|
|
|
r.buf = r.scanner.Bytes()
|
|
}
|
|
|
|
// Write out as much data as we can to the buffer, storing the rest
|
|
// for the next read.
|
|
n = len(p)
|
|
if n > len(r.buf) {
|
|
n = len(r.buf)
|
|
}
|
|
copy(p, r.buf)
|
|
r.buf = r.buf[n:]
|
|
|
|
return
|
|
}
|
|
|
|
// scanUnixLine is a bufio.Scanner SplitFunc. It tokenizes on lines, but
|
|
// only returns unix-style lines. So even if the line is "one\r\n", the
|
|
// token returned will be "one\n".
|
|
func scanUnixLine(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
|
advance, token, err = bufio.ScanLines(data, atEOF)
|
|
if advance == 0 {
|
|
// If we reached the end of a line without a newline, then
|
|
// just return as it is. Otherwise the Scanner will keep trying
|
|
// to scan, blocking forever.
|
|
return
|
|
}
|
|
|
|
return advance, append(token, '\n'), err
|
|
}
|