Skip to content

Commit

Permalink
usage, completion: assume executable is always lowercase
Browse files Browse the repository at this point in the history
When running on a case-insensitive platform / filesystem, the user
can invoke the executable using any case (e.g., "bUiLdX"). In situations
where buildx is running standalone, we use os.Args to determine the
name of the executable, and this information is used by Cobra to
print "Usage" output as well as generating the shell-completion
scripts.

Unfortunately, neither [os.Executable] nor [os.Stat] provide information
about the actual name of the executable, and the "correct" solution would
be to use [os.File.Readdirnames], which is a rather heavy hammer to use
just for this.

This patch assumes the executable to be named lowercase, regardless of
how it's invoked, on macOS and Windows (usually case-insensitive platforms).

It's worth noting that there's a corner-case to this corner-case; both
Windows and macOS can be configured to use a case-sensitive filesystem
(on Windows, this can be configured per-Directory). If that is the case,
and the executable is not lowercase, the generated shell-completion script
will be invalid.

Let's assume that's not the case, and that the user did not rename the
executable to anything uppercase.

Before this patch:

    ./bin/build/bUiLdX --help | head -n 5
    Extended build capabilities with BuildKit

    Usage:
      bUiLdX
      bUiLdX [command]

    ./bin/build/bUiLdX completion bash | head -n 3
    # bash completion V2 for bUiLdX                               -*- shell-script -*-

    __bUiLdX_debug()

With this patch applied:

    ./bin/build/bUiLdX --help | head -n 5
    Extended build capabilities with BuildKit

    Usage:
      buildx
      buildx [command]

    ./bin/build/bUiLdX completion bash | head -n 3
    # bash completion V2 for buildx                               -*- shell-script -*-

    __buildx_debug()

[os.Executable]: https://pkg.go.dev/os#Executable
[os.Stat]: https://pkg.go.dev/os#Stat
[os.File.Readdirnames]: https://pkg.go.dev/os#File.Readdirnames

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
thaJeztah committed Jan 25, 2025
1 parent bb4bef2 commit d636c73
Showing 1 changed file with 26 additions and 0 deletions.
26 changes: 26 additions & 0 deletions cmd/buildx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"

"github.com/docker/buildx/commands"
controllererrors "github.com/docker/buildx/controller/errdefs"
Expand Down Expand Up @@ -43,6 +45,30 @@ func runStandalone(cmd *command.DockerCli) error {
defer flushMetrics(cmd)

executable := os.Args[0]
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
// Note that we're cutting some corners here. The intent here
// is for both "usage" and shell-completion scripts to use the
// name of the executable with its actual (lower, upper) case.
// However, on case-insensitive platforms, the user can invoke
// the executable using any case (e.g., "bUiLdX").
//
// Unfortunately, neither [os.Executable] nor [os.Stat] provide
// this information, and the "correct" solution would be to use
// [os.File.Readdirnames], which is a rather heavy hammer to use
// just for this.
//
// So, on macOS and Windows (usually case-insensitive platforms)
// we assume the executable is always lower-case, but it's worth
// noting that there's a corner-case to this corner-case; both
// Windows and macOS can be configured to use a case-sensitive
// filesystem (on Windows, this can be configured per-Directory).
// If that is the case, and the executable is not lowercase, the
// generated shell-completion script will be invalid.
//
// Let's assume that's not the case, and that the user did not
// rename the executable to anything uppercase.
executable = strings.ToLower(executable)
}
rootCmd := commands.NewRootCmd(filepath.Base(executable), false, cmd)
return rootCmd.Execute()
}
Expand Down

0 comments on commit d636c73

Please sign in to comment.