Skip to content

Commit

Permalink
Merge pull request #449 from mutagen-io/v016-backports
Browse files Browse the repository at this point in the history
all: backport changes for v0.16.6
  • Loading branch information
xenoscopic committed May 4, 2023
2 parents 4019acd + a271189 commit afed45f
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 37 deletions.
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)
}

0 comments on commit afed45f

Please sign in to comment.