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

can specify the output format as text or json #106

Merged
merged 8 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.55.2
version: v1.57.2

60 changes: 42 additions & 18 deletions cmd/puku/puku.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ var opts = struct {
} `positional-args:"true"`
} `command:"fmt" description:"Format build files in the provided paths"`
Sync struct {
Write bool `short:"w" long:"write" description:"Whether to write the files back or just print them to stdout"`
Format string `short:"f" long:"format" choice:"json" choice:"text" default:"text" description:"output format when outputting to stdout"` //nolint
Write bool `short:"w" long:"write" description:"Whether to write the files back or just print them to stdout"`
} `command:"sync" description:"Synchronises the go.mod to the third party build file"`
Lint struct {
Args struct {
Format string `short:"f" long:"format" choice:"json" choice:"text" default:"text" description:"output format when outputting to stdout"` //nolint
Args struct {
Paths []string `positional-arg-name:"packages" description:"The packages to process"`
} `positional-args:"true"`
} `command:"lint" description:"Lint build files in the provided paths"`
Expand All @@ -44,6 +46,7 @@ var opts = struct {
} `command:"watch" description:"Watch build files in the provided paths and update them when needed"`
Migrate struct {
Write bool `short:"w" long:"write" description:"Whether to write the files back or just print them to stdout"`
Format string `short:"f" long:"format" choice:"json" choice:"text" default:"text" description:"output format when outputting to stdout"` //nolint
ThirdPartyDirs []string `long:"third_party_dir" description:"Directories to find go_module rules to migrate"`
UpdateGoMod bool `short:"g" long:"update_go_mod" description:"Update the go mod with the module(s) being migrated"`
Args struct {
Expand All @@ -52,8 +55,9 @@ var opts = struct {
} `command:"migrate" description:"Migrates from go_module to go_repo"`
Licenses struct {
Update struct {
Write bool `short:"w" long:"write" description:"Whether to write the files back or just print them to stdout"`
Args struct {
Format string `short:"f" long:"format" choice:"json" choice:"text" default:"text" description:"output format when outputting to stdout"` //nolint
Write bool `short:"w" long:"write" description:"Whether to write the files back or just print them to stdout"`
Args struct {
Paths []string `positional-arg-name:"packages" description:"The packages to process"`
} `positional-args:"true"`
} `command:"update" description:"Updates licences in the given paths"`
Expand All @@ -67,30 +71,37 @@ puku is a tool used to generate and update Go targets in build files
var log = logging.GetLogger()

var funcs = map[string]func(conf *config.Config, plzConf *please.Config, orignalWD string) int{
"fmt": func(conf *config.Config, plzConf *please.Config, orignalWD string) int {
"fmt": func(_ *config.Config, plzConf *please.Config, orignalWD string) int {
paths := work.MustExpandPaths(orignalWD, opts.Fmt.Args.Paths)
if err := generate.Update(true, plzConf, paths...); err != nil {
if err := generate.Update(plzConf, paths...); err != nil {
log.Fatalf("%v", err)
}
return 0
},
"sync": func(conf *config.Config, plzConf *please.Config, orignalWD string) int {
"sync": func(_ *config.Config, plzConf *please.Config, _ string) int {
g := graph.New(plzConf.BuildFileNames())
if err := sync.Sync(plzConf, g, opts.Sync.Write); err != nil {
log.Fatalf("%v", err)
if opts.Sync.Write {
if err := sync.Sync(plzConf, g); err != nil {
log.Fatalf("%v", err)
}
} else {
if err := sync.SyncToStdout(opts.Sync.Format, plzConf, g); err != nil {
log.Fatalf("%v", err)
}
}
return 0
},
"lint": func(conf *config.Config, plzConf *please.Config, orignalWD string) int {
"lint": func(_ *config.Config, plzConf *please.Config, orignalWD string) int {

paths := work.MustExpandPaths(orignalWD, opts.Lint.Args.Paths)
if err := generate.Update(false, plzConf, paths...); err != nil {
if err := generate.UpdateToStdout(opts.Lint.Format, plzConf, paths...); err != nil {
log.Fatalf("%v", err)
}
return 0
},
"watch": func(conf *config.Config, plzConf *please.Config, orignalWD string) int {
"watch": func(_ *config.Config, plzConf *please.Config, orignalWD string) int {
paths := work.MustExpandPaths(orignalWD, opts.Watch.Args.Paths)
if err := generate.Update(true, plzConf, paths...); err != nil {
if err := generate.Update(plzConf, paths...); err != nil {
log.Fatalf("%v", err)
}

Expand All @@ -105,15 +116,28 @@ var funcs = map[string]func(conf *config.Config, plzConf *please.Config, orignal
paths = []string{conf.GetThirdPartyDir()}
}
paths = work.MustExpandPaths(orignalWD, paths)
if err := migrate.Migrate(conf, plzConf, opts.Migrate.Write, opts.Migrate.UpdateGoMod, opts.Migrate.Args.Modules, paths); err != nil {
log.Fatalf("%v", err)
if opts.Migrate.Write {
if err := migrate.Migrate(conf, plzConf, opts.Migrate.UpdateGoMod, opts.Migrate.Args.Modules, paths); err != nil {
log.Fatalf("%v", err)
}
} else {
if err := migrate.MigrateToStdout(opts.Migrate.Format, conf, plzConf, opts.Migrate.UpdateGoMod, opts.Migrate.Args.Modules, paths); err != nil {
log.Fatalf("%v", err)
}
}
return 0
},
"update": func(conf *config.Config, plzConf *please.Config, orignalWD string) int {
"update": func(_ *config.Config, plzConf *please.Config, orignalWD string) int {
paths := work.MustExpandPaths(orignalWD, opts.Licenses.Update.Args.Paths)
if err := licences.New(proxy.New(proxy.DefaultURL), graph.New(plzConf.BuildFileNames())).Update(paths, opts.Licenses.Update.Write); err != nil {
log.Fatalf("%v", err)
l := licences.New(proxy.New(proxy.DefaultURL), graph.New(plzConf.BuildFileNames()))
if opts.Licenses.Update.Write {
if err := l.Update(paths); err != nil {
log.Fatalf("%v", err)
}
} else {
if err := l.UpdateToStdout(opts.Licenses.Update.Format, paths); err != nil {
log.Fatalf("%v", err)
}
}
return 0
},
Expand Down
34 changes: 20 additions & 14 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,24 @@ func newUpdater(conf *please.Config) *updater {
return newUpdaterWithGraph(g, conf)
}

func Update(write bool, plzConf *please.Config, paths ...string) error {
func Update(plzConf *please.Config, paths ...string) error {
u := newUpdater(plzConf)

conf, err := config.ReadConfig(".")
if err != nil {
if err := u.update(paths...); err != nil {
return err
}
u.paths = paths

if err := u.readAllModules(conf); err != nil {
return fmt.Errorf("failed to read third party rules: %v", err)
}
return u.graph.FormatFiles()
}

if err := u.update(conf); err != nil {
func UpdateToStdout(format string, plzConf *please.Config, paths ...string) error {
u := newUpdater(plzConf)
if err := u.update(paths...); err != nil {
return err
}

return u.graph.FormatFiles(write, os.Stdout)
return u.graph.FormatFilesWithWriter(os.Stdout, format)
}

func (u *updater) readAllModules(conf *config.Config) error {
return filepath.WalkDir(conf.GetThirdPartyDir(), func(path string, info fs.DirEntry, err error) error {
return filepath.WalkDir(conf.GetThirdPartyDir(), func(path string, info fs.DirEntry, _ error) error {
for _, buildFileName := range u.plzConf.BuildFileNames() {
if info.Name() == buildFileName {
file, err := u.graph.LoadFile(filepath.Dir(path))
Expand Down Expand Up @@ -144,7 +140,17 @@ func (u *updater) readModules(file *build.File) error {
}

// update loops through the provided paths, updating and creating any build rules it finds.
func (u *updater) update(conf *config.Config) error {
func (u *updater) update(paths ...string) error {
conf, err := config.ReadConfig(".")
if err != nil {
return err
}
u.paths = paths

if err := u.readAllModules(conf); err != nil {
return fmt.Errorf("failed to read third party rules: %v", err)
}

for _, path := range u.paths {
conf, err := config.ReadConfig(path)
if err != nil {
Expand Down
56 changes: 38 additions & 18 deletions graph/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package graph

import (
"bytes"
"encoding/json"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -122,12 +123,24 @@ func (g *Graph) loadFile(path string) (*build.File, error) {
return build.ParseBuild(validFilename, nil)
}

func (g *Graph) FormatFiles(write bool, out io.Writer) error {
func (g *Graph) FormatFilesWithWriter(out io.Writer, format string) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe should be FormatFilesToWriter

if err := g.ensureVisibilities(); err != nil {
return err
}
for _, file := range g.files {
if err := saveAndFormatBuildFile(file, write, out); err != nil {
if err := writeFormatedBuildFile(file, out, format); err != nil {
samwestmoreland marked this conversation as resolved.
Show resolved Hide resolved
return err
}
}
return nil
}

func (g *Graph) FormatFiles() error {
if err := g.ensureVisibilities(); err != nil {
return err
}
for _, file := range g.files {
if err := saveFormatedBuildFile(file); err != nil {
samwestmoreland marked this conversation as resolved.
Show resolved Hide resolved
return err
}
}
Expand Down Expand Up @@ -218,24 +231,11 @@ func checkVisibility(target labels.Label, visibilities []string) bool {
return false
}

func saveAndFormatBuildFile(buildFile *build.File, write bool, out io.Writer) error {
func writeFormatedBuildFile(buildFile *build.File, out io.Writer, format string) error {
samwestmoreland marked this conversation as resolved.
Show resolved Hide resolved
if len(buildFile.Stmt) == 0 {
return nil
}

if write {
f, err := os.Create(buildFile.Path)
if err != nil {
return err
}
defer f.Close()

_, err = f.Write(build.FormatWithoutRewriting(buildFile))
return err
}

target := build.FormatWithoutRewriting(buildFile)

actual, err := os.ReadFile(buildFile.Path)
if err != nil {
if !os.IsNotExist(err) {
Expand All @@ -245,9 +245,29 @@ func saveAndFormatBuildFile(buildFile *build.File, write bool, out io.Writer) er
}

if !bytes.Equal(target, actual) {
_, err := out.Write(target)
switch format {
case "text":
_, err := out.Write(target)
return err
case "json":
e := json.NewEncoder(out)
return e.Encode(struct{ Path, Content string }{Path: buildFile.Path, Content: string(target)})
}
}
return nil
}

func saveFormatedBuildFile(buildFile *build.File) error {
samwestmoreland marked this conversation as resolved.
Show resolved Hide resolved
if len(buildFile.Stmt) == 0 {
return nil
}

f, err := os.Create(buildFile.Path)
if err != nil {
return err
}
defer f.Close()

return nil
_, err = f.Write(build.FormatWithoutRewriting(buildFile))
return err
}
2 changes: 1 addition & 1 deletion graph/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ go_library(
})

bs := new(bytes.Buffer)
err = g.FormatFiles(false, bs)
err = g.FormatFilesWithWriter(bs, "text")
require.NoError(t, err)

fooT := edit.FindTargetByName(g.files["foo"], "foo")
Expand Down
19 changes: 16 additions & 3 deletions licences/licences.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,21 @@ func getLicences(modPaths []string) (map[string][]string, error) {
return ret, nil
}

func (l *Licenses) Update(paths []string, write bool) error {
func (l *Licenses) Update(paths []string) error {
if err := l.update(paths); err != nil {
return err
}
return l.graph.FormatFiles()
}

func (l *Licenses) UpdateToStdout(format string, paths []string) error {
if err := l.update(paths); err != nil {
return err
}
return l.graph.FormatFilesWithWriter(os.Stdout, format)
}

func (l *Licenses) update(paths []string) error {
var mods []string
rules := make(map[string]*build.Rule)

Expand Down Expand Up @@ -115,8 +129,7 @@ func (l *Licenses) Update(paths []string, write bool) error {
rules[mod].SetAttr("licences", edit.NewStringList(license))
}
}

return l.graph.FormatFiles(write, os.Stdout)
return nil
}

func (l *Licenses) Get(mod, ver string) ([]string, error) {
Expand Down
2 changes: 1 addition & 1 deletion licences/licences_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ go_repo(
graph: g,
}

err = l.Update([]string{"third_party/go"}, false)
err = l.UpdateToStdout("text", []string{"third_party/go"})
require.NoError(t, err)

testify := edit.FindTargetByName(thirdPartFile, "testify")
Expand Down
24 changes: 19 additions & 5 deletions migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,32 @@ type migrator struct {
licences *licences.Licenses
}

func Migrate(conf *config.Config, plzConf *please.Config, write, updateGoMod bool, modules, paths []string) error {
func newMigrator(plzConf *please.Config, conf *config.Config) *migrator {
g := graph.New(plzConf.BuildFileNames())
m := &migrator{
return &migrator{
plzConf: plzConf,
graph: g,
thirdPartyFolder: conf.GetThirdPartyDir(),
moduleRules: map[string]*moduleParts{},
licences: licences.New(proxy.New(proxy.DefaultURL), g),
existingRepoRules: map[string]*build.Rule{},
}
}

func Migrate(conf *config.Config, plzConf *please.Config, updateGoMod bool, modules, paths []string) error {
m := newMigrator(plzConf, conf)
if err := m.migrate(modules, paths, updateGoMod); err != nil {
return err
}
return m.graph.FormatFiles()
}

return m.migrate(modules, paths, write, updateGoMod)
func MigrateToStdout(format string, conf *config.Config, plzConf *please.Config, updateGoMod bool, modules, paths []string) error { //nolint
m := newMigrator(plzConf, conf)
if err := m.migrate(modules, paths, updateGoMod); err != nil {
return err
}
return m.graph.FormatFilesWithWriter(os.Stdout, format)
}

// pkgRule represents the rule expr in a pkg
Expand Down Expand Up @@ -125,7 +139,7 @@ func binaryAlias(module, thirdPartyDir string, part *pkgRule) (*build.Rule, erro
return rule, nil
}

func (m *migrator) migrate(modules, paths []string, write, updateGoMod bool) error {
func (m *migrator) migrate(modules, paths []string, updateGoMod bool) error {
// Read all the BUILD files under the provided paths to find go_module and go_mod_download rules
for _, path := range paths {
f, err := m.graph.LoadFile(path)
Expand All @@ -144,7 +158,7 @@ func (m *migrator) migrate(modules, paths []string, write, updateGoMod bool) err
if err := m.replaceRulesForModules(updateGoMod, modules); err != nil {
return err
}
return m.graph.FormatFiles(write, os.Stdout)
return nil
}

// replaceRulesForModules takes a list of modules and replaces those modules and their dependencies
Expand Down
Loading
Loading