Skip to content

Commit

Permalink
Use new findpkg.ResolveGlobs function
Browse files Browse the repository at this point in the history
Allows resolving of both file system and Go package paths & globs;
introduces GBB_PATH support.

Signed-off-by: Chris Koch <[email protected]>
  • Loading branch information
hugelgupf committed Dec 29, 2022
1 parent 20456a6 commit abc3eb8
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 259 deletions.
113 changes: 13 additions & 100 deletions pkg/uroot/uroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"path/filepath"
"strings"

"github.com/u-root/gobusybox/src/pkg/bb/findpkg"
gbbgolang "github.com/u-root/gobusybox/src/pkg/golang"
"github.com/u-root/u-root/pkg/cpio"
"github.com/u-root/u-root/pkg/golang"
Expand Down Expand Up @@ -237,13 +238,23 @@ func CreateInitramfs(logger ulog.Logger, opts Opts) error {

files := initramfs.NewFiles()

lookupEnv := findpkg.DefaultEnv()
if opts.UrootSource != "" {
lookupEnv.URootSource = opts.UrootSource
}

env := gbbgolang.Environ{
Context: opts.Env.Context,
GO111MODULE: os.Getenv("GO111MODULE"),
}

// Expand commands.
for index, cmds := range opts.Commands {
directoryPaths, err := ResolvePackagePaths(logger, opts.Env, opts.UrootSource, cmds.Packages)
paths, err := findpkg.ResolveGlobs(logger, env, lookupEnv, cmds.Packages)
if err != nil {
return err
}
opts.Commands[index].Packages = directoryPaths
opts.Commands[index].Packages = paths
}

// Make sure this isn't a nil pointer
Expand Down Expand Up @@ -336,61 +347,6 @@ func (o *Opts) addSymlinkTo(logger ulog.Logger, archive *initramfs.Opts, command
return nil
}

// resolvePackagePath finds import paths for a single import path or directory string.
//
// Possible options are:
//
// ./foobar
// ./foobar/glob*
// cmds/core/ip with UROOT_SOURCE=/directory/to/u-root
// cmds/core/g*lob with UROOT_SOURCE=/directory/to/u-root
func resolvePackagePath(logger ulog.Logger, env golang.Environ, urootSource string, input string) ([]string, error) {
// In case the input is a u-root import path we strip the prefix here
// so that it can get re-added with a proper filepath.
input = strings.TrimPrefix(input, "github.com/u-root/u-root/")

// Search the current working directory, as well as the uroot source path if specified
prefixes := []string{""}
if len(urootSource) != 0 {
prefixes = append(prefixes, urootSource)
}

// Resolve file system paths to package import paths.
for _, prefix := range prefixes {
path := filepath.Join(prefix, input)
matches, err := filepath.Glob(path)
if len(matches) == 0 || err != nil {
continue
}

var directories []string
for _, match := range matches {
// Only match directories for building.
// Skip anything that is not a directory
fileInfo, _ := os.Stat(match)
if !fileInfo.IsDir() {
continue
}
absPath, _ := filepath.Abs(match)

if _, err := env.PackageByPath(match); err != nil {
logger.Printf("Skipping package %q: %v", match, err)
} else {
directories = append(directories, absPath)
}
}
return directories, nil
}

// No file import paths found. Check if pkg still resolves as a package name.
pkg, err := env.Package(input)
if err != nil {
return nil, fmt.Errorf("%q is neither package or path/glob: %v", input, err)
}
absDir, _ := filepath.Abs(pkg.Dir)
return []string{absDir}, nil
}

func resolveCommandOrPath(cmd string, cmds []Commands) (string, error) {
if strings.ContainsRune(cmd, filepath.Separator) {
return cmd, nil
Expand All @@ -411,49 +367,6 @@ func resolveCommandOrPath(cmd string, cmds []Commands) (string, error) {
return "", fmt.Errorf("command or path %q not included in u-root build", cmd)
}

// ResolvePackagePaths takes a list of u-root command paths and directories
// and turns them into exclusively absolute directory paths.
//
// Currently allowed formats:
//
// - paths to package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/ls
// - globs of paths to package directories; e.g. ./cmds/*
// - u-root package paths; e.g. cmds/core/ls or github.com/u-root/u-root/cmds/core/ls
// - globs of u-root package paths, e.g. cmds/* or github.com/u-root/u-root/cmds/*
// - if an entry starts with "-" it excludes the matching package(s)
//
// Directories may be relative or absolute, with or without globs.
// Globs are resolved using filepath.Glob.
func ResolvePackagePaths(logger ulog.Logger, env golang.Environ, urootSource string, pkgs []string) ([]string, error) {
var includes []string
excludes := map[string]bool{}
for _, pkg := range pkgs {
isExclude := strings.HasPrefix(pkg, "-")

if isExclude {
pkg = pkg[1:]
}
paths, err := resolvePackagePath(logger, env, urootSource, pkg)
if err != nil {
return nil, err
}
if !isExclude {
includes = append(includes, paths...)
} else {
for _, p := range paths {
excludes[p] = true
}
}
}
var result []string
for _, p := range includes {
if !excludes[p] {
result = append(result, p)
}
}
return result, nil
}

// ParseExtraFiles adds files from the extraFiles list to the archive.
//
// The following formats are allowed in the extraFiles list:
Expand Down
145 changes: 0 additions & 145 deletions pkg/uroot/uroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"log"
"os"
"path/filepath"
"reflect"
"syscall"
"testing"

Expand All @@ -26,150 +25,6 @@ type inMemArchive struct {
// Finish implements initramfs.Writer.Finish.
func (inMemArchive) Finish() error { return nil }

func TestResolvePackagePaths(t *testing.T) {
defaultEnv := golang.Default()
urootpath, err := filepath.Abs("../../")
if err != nil {
t.Fatalf("failure to set up test: %v", err)
}
gopath1, err := filepath.Abs("test/gopath1")
if err != nil {
t.Fatalf("failure to set up test: %v", err)
}
gopath2, err := filepath.Abs("test/gopath2")
if err != nil {
t.Fatalf("failure to set up test: %v", err)
}
gopath1Env := defaultEnv
gopath1Env.GOPATH = gopath1
gopath2Env := defaultEnv
gopath2Env.GOPATH = gopath2
everythingEnv := defaultEnv
everythingEnv.GOPATH = gopath1 + ":" + gopath2
foopath, err := filepath.Abs("test/gopath1/src/foo")
if err != nil {
t.Fatalf("failure to set up test: %v", err)
}

// Why doesn't the log package export this as a default?
l := log.New(os.Stdout, "", log.LstdFlags)

for _, tc := range []struct {
env golang.Environ
in []string
expected []string
wantErr bool
}{
// Nonexistent Package
{
env: defaultEnv,
in: []string{"fakepackagename"},
expected: nil,
wantErr: true,
},
// Single go package import
{
env: defaultEnv,
in: []string{"github.com/u-root/u-root/cmds/core/ls"},
expected: []string{filepath.Join(urootpath, "cmds/core/ls")},
wantErr: false,
},
// Single package directory relative to working dir
{
env: defaultEnv,
in: []string{"test/gopath1/src/foo"},
expected: []string{filepath.Join(urootpath, "/pkg/uroot/test/gopath1/src/foo")},
wantErr: false,
},
// Single package directory with absolute path
{
env: defaultEnv,
in: []string{foopath},
expected: []string{filepath.Join(urootpath, "pkg/uroot/test/gopath1/src/foo")},
wantErr: false,
},
// Single package directory relative to GOPATH
{
env: gopath1Env,
in: []string{filepath.Join(gopath1, "src/foo")},
expected: []string{filepath.Join(urootpath, "pkg/uroot/test/gopath1/src/foo")},
wantErr: false,
},
// Package directory glob
{
env: defaultEnv,
in: []string{"test/gopath2/src/mypkg*"},
expected: []string{
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkga"),
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkgb"),
},
wantErr: false,
},
// GOPATH glob
{
env: gopath2Env,
in: []string{filepath.Join(gopath2, "src/mypkg*")},
expected: []string{
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkga"),
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkgb"),
},
wantErr: false,
},
// Single ambiguous package - exists in both GOROOT and GOPATH
// This test doesn't work anymore with file paths
// {
// env: gopath1Env,
// in: []string{"os"},
// expected: []string{
// "os",
// },
// wantErr: false,
// },
// Packages from different gopaths
{
env: everythingEnv,
in: []string{filepath.Join(gopath1, "src/foo"), filepath.Join(gopath2, "src/mypkga")},
expected: []string{
filepath.Join(urootpath, "pkg/uroot/test/gopath1/src/foo"),
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkga"),
},
wantErr: false,
},
// Same package specified twice
{
env: defaultEnv,
in: []string{"test/gopath2/src/mypkga", "test/gopath2/src/mypkga"},
// TODO: This returns the package twice. Is this preferred?
expected: []string{
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkga"),
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkga"),
},
wantErr: false,
},
// Excludes
{
env: defaultEnv,
in: []string{"test/gopath2/src/*", "-test/gopath2/src/mypkga"},
expected: []string{
filepath.Join(urootpath, "pkg/uroot/test/gopath2/src/mypkgb"),
},
wantErr: false,
},
} {
t.Run(fmt.Sprintf("%q", tc.in), func(t *testing.T) {
out, err := ResolvePackagePaths(l, tc.env, urootpath, tc.in)
if (err != nil) != tc.wantErr {
t.Fatalf("ResolvePackagePaths(%#v, %v) err != nil is %v, want %v\nerr is %v",
tc.env, tc.in, err != nil, tc.wantErr, err)
}
if !reflect.DeepEqual(out, tc.expected) {
t.Errorf("ResolvePackagePaths(%#v, %v) = %v; want %v",
tc.env, tc.in, out, tc.expected)
}
})
}
}

func TestCreateInitramfs(t *testing.T) {
dir := t.TempDir()
syscall.Umask(0)
Expand Down
15 changes: 1 addition & 14 deletions u-root.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,23 +319,10 @@ func Main(l ulog.Logger, buildOpts *gbbgolang.BuildOpts) error {
pkgs = append(pkgs, a)
continue
}
// This is reached if a template was selected, so check uroot source path
// To make things a easier on our poor users, do
// validation so the error is a little less mysterious.
if err := canFindSource(*urootSourceDir); err != nil {
return err
}
for _, pkg := range p {
pkg = strings.TrimPrefix(pkg, "github.com/u-root/u-root/")
pkgs = append(pkgs, filepath.Join(*urootSourceDir, pkg))
}
pkgs = append(pkgs, p...)
}
if len(pkgs) == 0 {
if err := canFindSource(*urootSourceDir); err != nil {
return err
}
pkgs = []string{filepath.Join(*urootSourceDir, "cmds/core/*")}
pkgs = []string{"github.com/u-root/u-root/cmds/core/*"}
}

// The command-line tool only allows specifying one build mode
Expand Down

0 comments on commit abc3eb8

Please sign in to comment.