Skip to content

Commit

Permalink
u-root command: add checkArgs function
Browse files Browse the repository at this point in the history
There are errors which have confusing diagnostics.

A typical one is this
u-root -files `which ethtool` -files `which bash` all

if ethtool is not installed, this expands to
u-root -files -files `which bash` all
and a warning that is very confusing:
Skipping /usr/bin/bash because it is not a directory

This is not even remotely related to the problem.

Still worse, this command will create a badly broken initrd!

This problem has been known to hold up interns for weeks at a time :-)

Add checkArgs, which looks for common problems in os.Args,
and is easily expanded. Add a test.

Signed-off-by: Ronald G. Minnich <[email protected]>
  • Loading branch information
rminnich committed Mar 23, 2023
1 parent 107f179 commit 5203ef2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
39 changes: 39 additions & 0 deletions u-root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main

import (
"encoding/json"
"errors"
"flag"
"fmt"
"log"
Expand Down Expand Up @@ -37,6 +38,11 @@ func (m *multiFlag) Set(value string) error {
return nil
}

// errors from the u-root command
var (
ErrEmptyFilesArg = errors.New("Empty argument to -files")
)

// Flags for u-root builder.
var (
build, format, tmpDir, base, outputPath *string
Expand Down Expand Up @@ -146,7 +152,40 @@ func generateLabel(env gbbgolang.Environ) string {
return fmt.Sprintf("%s-%s-%s-%s", *build, env.GOOS, env.GOARCH, strings.Join(baseCmds, "_"))
}

// checkArgs checks for common mistakes that cause confusion.
// 1. -files as the last argument
// 2. -files followed by any switch, indicating a shell expansion problem
// This is usually caused by Makfiles structured as follows
// u-root -files `which ethtool` -files `which bash`
// if ethtool is not installed, the expansion yields
// u-root -files -files `which bash`
// and the rather confusing error message
// 16:14:51 Skipping /usr/bin/bash because it is not a directory
// which, in practice, nobody understands
func checkArgs(args ...string) error {
if len(args) == 0 {
return nil
}

if args[len(args)-1] == "-files" {
return fmt.Errorf("last argument is -files:%w", ErrEmptyFilesArg)
}

// We know the last arg is not -files; scan the arguments for -files
// followed by a switch.
for i := 0; i < len(args)-1; i++ {
if args[i] == "-files" && args[i+1][0] == '-' {
return fmt.Errorf("-files argument %d is followed by a switch: %w", i, ErrEmptyFilesArg)
}
}

return nil
}

func main() {
if err := checkArgs(os.Args...); err != nil {
log.Fatal(err)
}
gbbOpts := &gbbgolang.BuildOpts{}
gbbOpts.RegisterFlags(flag.CommandLine)

Expand Down
22 changes: 22 additions & 0 deletions uroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"crypto/sha256"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -357,3 +358,24 @@ func buildIt(t *testing.T, args, env []string, want error) (*os.File, []byte) {
func TestMain(m *testing.M) {
testutil.Run(m, main)
}

func TestCheckArgs(t *testing.T) {
for _, tt := range []struct {
name string
args []string
err error
}{
{"-files is only arg", []string{"-files"}, ErrEmptyFilesArg},
{"-files followed by -files", []string{"-files", "-files"}, ErrEmptyFilesArg},
{"-files followed by any other switch", []string{"-files", "-abc"}, ErrEmptyFilesArg},
{"no args", []string{}, nil},
{"u-root alone", []string{"u-root"}, nil},
{"u-root with -files and other args", []string{"u-root", "-files", "/bin/bash", "core"}, nil},
} {
t.Run(tt.name, func(t *testing.T) {
if err := checkArgs(tt.args...); !errors.Is(err, tt.err) {
t.Errorf("%q: got %v, want %v", tt.args, err, tt.err)
}
})
}
}

0 comments on commit 5203ef2

Please sign in to comment.