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

all: backport changes for v0.16.6 #449

Merged
merged 4 commits into from
May 4, 2023
Merged
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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.19.6'
go-version: '1.19.9'
- name: "Install sha256sum"
run: brew install coreutils
- run: scripts/ci/setup_go.sh
Expand Down Expand Up @@ -74,7 +74,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.19.6'
go-version: '1.19.9'
- run: scripts/ci/setup_go.sh
- run: scripts/ci/setup_ssh.sh
- run: scripts/ci/setup_docker.sh
Expand All @@ -90,7 +90,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.19.6'
go-version: '1.19.9'
- run: scripts/ci/setup_go.sh
shell: bash
- run: scripts/ci/setup_docker.sh
Expand All @@ -113,7 +113,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '1.19.6'
go-version: '1.19.9'
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- uses: docker/login-action@v1
Expand Down
5 changes: 4 additions & 1 deletion cmd/mutagen/common/templating/templating.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"strings"
"text/template"

"github.com/mutagen-io/mutagen/pkg/platform/terminal"
)

// jsonify is the built-in JSON encoder that's made available to templates.
Expand Down Expand Up @@ -33,6 +35,7 @@ func jsonify(value any) (string, error) {

// builtins are the builtin functions supported in output templates.
var builtins = template.FuncMap{
"json": jsonify,
"json": jsonify,
"shellSanitize": terminal.NeutralizeControlCharacters,
// TODO: Figure out what other functions we want to include here, if any.
}
5 changes: 3 additions & 2 deletions cmd/mutagen/forward/list_monitor_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/mutagen-io/mutagen/cmd/mutagen/common"

"github.com/mutagen-io/mutagen/pkg/forwarding"
"github.com/mutagen-io/mutagen/pkg/platform/terminal"
"github.com/mutagen-io/mutagen/pkg/selection"
"github.com/mutagen-io/mutagen/pkg/url"
)
Expand All @@ -27,7 +28,7 @@ func printEndpoint(name string, url *url.URL, configuration *forwarding.Configur
fmt.Printf("%s:\n", name)

// Print the URL.
fmt.Println("\tURL:", url.Format("\n\t\t"))
fmt.Println("\tURL:", terminal.NeutralizeControlCharacters(url.Format("\n\t\t")))

// Print configuration information if desired.
if mode == common.SessionDisplayModeListLong || mode == common.SessionDisplayModeMonitorLong {
Expand Down Expand Up @@ -142,7 +143,7 @@ func printSession(state *forwarding.State, mode common.SessionDisplayMode) {

// Print the last error, if any.
if state.LastError != "" {
color.Red("Last error: %s\n", state.LastError)
color.Red("Last error: %s\n", terminal.NeutralizeControlCharacters(state.LastError))
}

// Print the session status .
Expand Down
4 changes: 2 additions & 2 deletions cmd/mutagen/forward/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error {
defer daemonConnection.Close()

// Create a session service client.
sessionService := forwardingsvc.NewForwardingClient(daemonConnection)
forwardingService := forwardingsvc.NewForwardingClient(daemonConnection)

// Create the list request that we'll use.
request := &forwardingsvc.ListRequest{
Expand Down Expand Up @@ -126,7 +126,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error {
lastUpdateTime = now

// Perform a list operation.
response, err := sessionService.List(context.Background(), request)
response, err := forwardingService.List(context.Background(), request)
if err != nil {
return fmt.Errorf("list failed: %w", grpcutil.PeelAwayRPCErrorLayer(err))
} else if err = response.EnsureValid(); err != nil {
Expand Down
15 changes: 11 additions & 4 deletions cmd/mutagen/project/common_windows.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package project

import (
"errors"
"os"
"os/exec"
"path/filepath"
)

// runInShell runs the specified command using the system shell. On Windows
// systems, this is %COMSPEC% (with a fallback to cmd.exe if unspecified).
// systems, this is %ComSpec% (with a fallback to a fully qualified cmd.exe if
// %ComSpec% is not an absolute path (which includes cases where it's empty)).
func runInShell(command string) error {
// Determine the shell to use.
shell := os.Getenv("COMSPEC")
if shell == "" {
shell = "cmd.exe"
shell := os.Getenv("ComSpec")
if !filepath.IsAbs(shell) {
systemRoot := os.Getenv("SystemRoot")
if !filepath.IsAbs(systemRoot) {
return errors.New("invalid ComSpec and SystemRoot environment variables")
}
shell = filepath.Join(systemRoot, "System32", "cmd.exe")
}

// Set up the process.
Expand Down
37 changes: 22 additions & 15 deletions cmd/mutagen/sync/list_monitor_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/mutagen-io/mutagen/cmd/mutagen/common"

"github.com/mutagen-io/mutagen/pkg/platform/terminal"
"github.com/mutagen-io/mutagen/pkg/selection"
"github.com/mutagen-io/mutagen/pkg/synchronization"
"github.com/mutagen-io/mutagen/pkg/synchronization/core"
Expand Down Expand Up @@ -87,7 +88,7 @@ func printEndpoint(name string, url *url.URL, configuration *synchronization.Con
fmt.Printf("%s:\n", name)

// Print the URL.
fmt.Println("\tURL:", url.Format("\n\t\t"))
fmt.Println("\tURL:", terminal.NeutralizeControlCharacters(url.Format("\n\t\t")))

// Print configuration information if desired.
if mode == common.SessionDisplayModeListLong || mode == common.SessionDisplayModeMonitorLong {
Expand Down Expand Up @@ -157,14 +158,14 @@ func printEndpoint(name string, url *url.URL, configuration *synchronization.Con
if configuration.DefaultOwner != "" {
defaultOwnerDescription = configuration.DefaultOwner
}
fmt.Println("\t\tDefault file/directory owner:", defaultOwnerDescription)
fmt.Println("\t\tDefault file/directory owner:", terminal.NeutralizeControlCharacters(defaultOwnerDescription))

// Compute and print the default file/directory group.
defaultGroupDescription := "Default"
if configuration.DefaultGroup != "" {
defaultGroupDescription = configuration.DefaultGroup
}
fmt.Println("\t\tDefault file/directory group:", defaultGroupDescription)
fmt.Println("\t\tDefault file/directory group:", terminal.NeutralizeControlCharacters(defaultGroupDescription))
}

// At this point, there's no other status information that will be displayed
Expand Down Expand Up @@ -195,7 +196,10 @@ func printEndpoint(name string, url *url.URL, configuration *synchronization.Con
} else if mode == common.SessionDisplayModeListLong {
color.Red("\tScan problems:\n")
for _, p := range state.ScanProblems {
color.Red("\t\t%s: %v\n", formatPath(p.Path), p.Error)
color.Red("\t\t%s: %v\n",
terminal.NeutralizeControlCharacters(formatPath(p.Path)),
terminal.NeutralizeControlCharacters(p.Error),
)
}
if state.ExcludedScanProblems > 0 {
color.Red("\t\t...+%d more...\n", state.ExcludedScanProblems)
Expand All @@ -212,7 +216,10 @@ func printEndpoint(name string, url *url.URL, configuration *synchronization.Con
} else if mode == common.SessionDisplayModeListLong {
color.Red("\tTransition problems:\n")
for _, p := range state.TransitionProblems {
color.Red("\t\t%s: %v\n", formatPath(p.Path), p.Error)
color.Red("\t\t%s: %v\n",
terminal.NeutralizeControlCharacters(formatPath(p.Path)),
terminal.NeutralizeControlCharacters(p.Error),
)
}
if state.ExcludedTransitionProblems > 0 {
color.Red("\t\t...+%d more...\n", state.ExcludedTransitionProblems)
Expand All @@ -237,19 +244,19 @@ func printConflicts(conflicts []*core.Conflict, excludedConflicts uint64) {
for _, a := range c.AlphaChanges {
color.Red(
"\t(alpha) %s (%s -> %s)\n",
formatPath(a.Path),
formatEntry(a.Old),
formatEntry(a.New),
terminal.NeutralizeControlCharacters(formatPath(a.Path)),
terminal.NeutralizeControlCharacters(formatEntry(a.Old)),
terminal.NeutralizeControlCharacters(formatEntry(a.New)),
)
}

// Print the beta changes.
for _, b := range c.BetaChanges {
color.Red(
"\t(beta) %s (%s -> %s)\n",
formatPath(b.Path),
formatEntry(b.Old),
formatEntry(b.New),
terminal.NeutralizeControlCharacters(formatPath(b.Path)),
terminal.NeutralizeControlCharacters(formatEntry(b.Old)),
terminal.NeutralizeControlCharacters(formatEntry(b.New)),
)
}

Expand Down Expand Up @@ -356,15 +363,15 @@ func printSession(state *synchronization.State, mode common.SessionDisplayMode)
if len(configuration.DefaultIgnores) > 0 {
fmt.Println("\tDefault ignores:")
for _, p := range configuration.DefaultIgnores {
fmt.Printf("\t\t%s\n", p)
fmt.Printf("\t\t%s\n", terminal.NeutralizeControlCharacters(p))
}
}

// Print per-session ignores.
if len(configuration.Ignores) > 0 {
fmt.Println("\tIgnores:")
for _, p := range configuration.Ignores {
fmt.Printf("\t\t%s\n", p)
fmt.Printf("\t\t%s\n", terminal.NeutralizeControlCharacters(p))
}
} else {
fmt.Println("\tIgnores: None")
Expand Down Expand Up @@ -421,7 +428,7 @@ func printSession(state *synchronization.State, mode common.SessionDisplayMode)

// Print the last error, if any.
if state.LastError != "" {
color.Red("Last error: %s\n", state.LastError)
color.Red("Last error: %s\n", terminal.NeutralizeControlCharacters(state.LastError))
}

// Print the session status .
Expand Down Expand Up @@ -459,7 +466,7 @@ func printSession(state *synchronization.State, mode common.SessionDisplayMode)
stagingProgress.ReceivedFiles, stagingProgress.ExpectedFiles,
humanize.Bytes(stagingProgress.TotalReceivedSize), totalSizeDenominator,
100.0*fractionComplete,
stagingProgress.Path,
terminal.NeutralizeControlCharacters(stagingProgress.Path),
humanize.Bytes(stagingProgress.ReceivedSize), humanize.Bytes(stagingProgress.ExpectedSize),
)
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/mutagen/sync/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

synchronizationmodels "github.com/mutagen-io/mutagen/pkg/api/models/synchronization"
"github.com/mutagen-io/mutagen/pkg/grpcutil"
"github.com/mutagen-io/mutagen/pkg/platform/terminal"
selectionpkg "github.com/mutagen-io/mutagen/pkg/selection"
synchronizationsvc "github.com/mutagen-io/mutagen/pkg/service/synchronization"
"github.com/mutagen-io/mutagen/pkg/synchronization"
Expand Down Expand Up @@ -97,7 +98,7 @@ func computeMonitorStatusLine(state *synchronization.State) string {
stagingProgress.ReceivedFiles, stagingProgress.ExpectedFiles,
humanize.Bytes(stagingProgress.TotalReceivedSize), totalSizeDenominator,
100.0*fractionComplete,
path.Base(stagingProgress.Path),
terminal.NeutralizeControlCharacters(path.Base(stagingProgress.Path)),
humanize.Bytes(stagingProgress.ReceivedSize), humanize.Bytes(stagingProgress.ExpectedSize),
)
}
Expand Down Expand Up @@ -140,7 +141,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error {
defer daemonConnection.Close()

// Create a session service client.
sessionService := synchronizationsvc.NewSynchronizationClient(daemonConnection)
synchronizationService := synchronizationsvc.NewSynchronizationClient(daemonConnection)

// Create the list request that we'll use.
request := &synchronizationsvc.ListRequest{
Expand Down Expand Up @@ -176,7 +177,7 @@ func monitorMain(_ *cobra.Command, arguments []string) error {
lastUpdateTime = now

// Perform a list operation.
response, err := sessionService.List(context.Background(), request)
response, err := synchronizationService.List(context.Background(), request)
if err != nil {
return fmt.Errorf("list failed: %w", grpcutil.PeelAwayRPCErrorLayer(err))
} else if err = response.EnsureValid(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion images/sidecar/linux/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Use an Alpine-based Go builder.
FROM golang:1.19.6-alpine3.17 AS builder
FROM golang:1.19.9-alpine3.17 AS builder

# Disable cgo in order to match the behavior of our release binaries (and to
# avoid the need for gcc on certain architectures).
Expand Down
8 changes: 5 additions & 3 deletions pkg/agent/dial.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/mutagen-io/mutagen/pkg/filesystem"
"github.com/mutagen-io/mutagen/pkg/logging"
"github.com/mutagen-io/mutagen/pkg/mutagen"
"github.com/mutagen-io/mutagen/pkg/platform/terminal"
"github.com/mutagen-io/mutagen/pkg/prompting"
streampkg "github.com/mutagen-io/mutagen/pkg/stream"
)
Expand Down Expand Up @@ -129,13 +130,14 @@ func connect(logger *logging.Logger, transport Transport, mode, prompter string,
// which is all we care about.
stream.Close()

// Extract any error output, ensure that it's UTF-8, and strip out any
// whitespace (primarily trailing newlines).
// Extract any error output, ensure that it's UTF-8, strip out any
// whitespace (primarily trailing newlines), and neutralize any control
// characters.
errorOutput := errorBuffer.String()
if !utf8.ValidString(errorOutput) {
return nil, false, false, errors.New("remote did not return UTF-8 output")
}
errorOutput = strings.TrimSpace(errorOutput)
errorOutput = terminal.NeutralizeControlCharacters(strings.TrimSpace(errorOutput))

// Wrap up the handshake error with additional context.
if errorOutput != "" {
Expand Down
10 changes: 9 additions & 1 deletion pkg/logging/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

"github.com/mutagen-io/mutagen/pkg/platform/terminal"
"github.com/mutagen-io/mutagen/pkg/stream"
)

Expand All @@ -24,7 +25,8 @@ type Logger struct {

// NewLogger creates a new logger at the specified log level targeting the
// specified writer. The writer must be non-nil. The logger and any derived
// subloggers will coordinate access to the writer.
// subloggers will coordinate access to the writer. Any terminal control
// characters will be neutralized before being written to the log.
func NewLogger(level Level, writer io.Writer) *Logger {
return &Logger{
level: level,
Expand Down Expand Up @@ -109,6 +111,9 @@ func (l *Logger) write(timestamp time.Time, level Level, message string) {
)
}

// Neutralize any control characters in the line.
line = terminal.NeutralizeControlCharacters(line)

// Write the line. We can't do much with the error here, so we don't try.
// Practically speaking, most io.Writer implementations perform retries if a
// short write occurs, so retrying here (on top of that logic) probably
Expand Down Expand Up @@ -248,6 +253,9 @@ func (l *Logger) Writer(level Level) io.Writer {
line = line + "\n"
}

// Neutralize any control characters in the line.
line = terminal.NeutralizeControlCharacters(line)

// Write the line to the underlying writer.
l.writer.Write([]byte(line))
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/mutagen/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
// VersionMinor represents the current minor version of Mutagen.
VersionMinor = 16
// VersionPatch represents the current patch version of Mutagen.
VersionPatch = 5
VersionPatch = 6
// VersionTag represents a tag to be appended to the Mutagen version string.
// It must not contain spaces. If empty, no tag is appended to the version
// string.
Expand Down
2 changes: 2 additions & 0 deletions pkg/platform/terminal/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package terminal provides utilities for working with terminals.
package terminal
18 changes: 18 additions & 0 deletions pkg/platform/terminal/neutralization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package terminal

import (
"strings"
)

// controlCharacterNeutralizer is a string replacer that terminal neutralizes
// control characters.
var controlCharacterNeutralizer = strings.NewReplacer(
"\x1b", "^[",
"\r", "\\r",
)

// NeutralizeControlCharacters returns a copy of a string with any terminal
// control characters neutralized.
func NeutralizeControlCharacters(value string) string {
return controlCharacterNeutralizer.Replace(value)
}