package main
import (
"encoding/json"
"fmt"
"os"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
"text/template"
"github.com/urfave/cli"
"pagure.io/golist/pkg/util"
)
var (
version = "0.10.4"
)
func main() {
app := cli.NewApp()
app.Name = "golist"
app.Usage = "List Go project resources"
app.Version = fmt.Sprintf("%s (built with %s)", version, runtime.Version())
app.Flags = []cli.Flag{
cli.StringSliceFlag{
Name: "ignore-dir, d",
Usage: "Directory to ignore",
},
cli.StringSliceFlag{
Name: "ignore-tree, t",
Usage: "Directory tree to ignore",
},
cli.StringSliceFlag{
Name: "ignore-regex, r",
Usage: "Regex specified files/dirs to ignore",
},
cli.StringSliceFlag{
Name: "package-path",
Usage: "Package entry point",
},
cli.BoolFlag{
Name: "all-deps",
Usage: "List imported packages including stdlib",
},
cli.BoolFlag{
Name: "provided",
Usage: "List provided packages",
},
cli.BoolFlag{
Name: "imported",
Usage: "List imported packages",
},
cli.BoolFlag{
Name: "skip-self",
Usage: "Skip imported packages with the same --package-path",
},
cli.BoolFlag{
Name: "tests",
Usage: "Apply the listing options over tests only",
},
cli.BoolFlag{
Name: "with-tests",
Usage: "Apply the listing options over both the main package and the tests",
},
cli.BoolFlag{
Name: "show-main",
Usage: "Including main files in listings",
},
cli.BoolFlag{
Name: "to-install",
Usage: "List all resources recognized as essential part of the Go project",
},
cli.BoolFlag{
Name: "include-md",
Usage: "Include Markdown (.md) files in the recognized resources",
},
cli.StringSliceFlag{
Name: "include-extension, e",
Usage: "Include all files with the extension in the recognized resources, e.g. .proto, .tmpl",
Value: &cli.StringSlice{".proto", ".md", ".s"},
},
cli.BoolFlag{
Name: "json",
Usage: "Output as JSON artefact",
},
cli.StringFlag{
Name: "template",
Usage: "Template used to print output",
Value: `{{.}}\n`,
},
}
getTemplate := func(output_fmt string) (*template.Template, error) {
str, err := strconv.Unquote(`"` + output_fmt + `"`)
if err != nil {
return nil, fmt.Errorf("Unparseable template string: %v", err)
}
return template.New("output").Parse(str)
}
app.Action = func(c *cli.Context) error {
if len(c.StringSlice("package-path")) == 0 {
return fmt.Errorf("--package-path is not set")
}
if !c.Bool("provided") && !c.Bool("imported") && !c.Bool("to-install") && !c.Bool("json") {
return fmt.Errorf("At least one of --provided, --imported, --to-install or --json must be set")
}
tmpl, err := getTemplate(c.String("template"))
if err != nil {
return err
}
ignore := &util.Ignore{}
for _, dir := range c.StringSlice("ignore-tree") {
// skip all ignored dirs that are prefixes of the package-path
if strings.HasPrefix(c.String("package-path"), dir) {
continue
}
ignore.Trees = append(ignore.Trees, dir)
}
for _, dir := range c.StringSlice("ignore-dir") {
// skip all ignored dirs that are prefixes of the package-path
if strings.HasPrefix(c.String("package-path"), dir) && c.String("package-path") != dir {
continue
}
ignore.Dirs = append(ignore.Dirs, dir)
}
for _, dir := range c.StringSlice("ignore-regex") {
ignore.Regexes = append(ignore.Regexes, regexp.MustCompile(dir))
}
collector := util.NewPackageInfoCollector(ignore, c.Bool("include-md"), c.StringSlice("include-extension"))
for _, packagePath := range c.StringSlice("package-path") {
if err := collector.CollectPackageInfos(packagePath); err != nil {
return err
}
}
if c.Bool("json") {
// Collect everything
artifact, _ := collector.BuildArtifact()
str, _ := json.Marshal(artifact)
fmt.Printf("%v\n", string(str))
return nil
}
if c.Bool("provided") {
if c.Bool("with-tests") && c.Bool("tests") {
return fmt.Errorf("Both --with-tests and --tests cannot be set at the same time")
}
pkgs, err := collector.BuildPackageTree(c.Bool("show-main"), c.Bool("with-tests"), c.Bool("tests"))
if err != nil {
return err
}
sort.Strings(pkgs)
for _, item := range pkgs {
err := tmpl.Execute(os.Stdout, item)
if err != nil {
return err
}
}
return nil
}
if c.Bool("imported") {
if c.Bool("with-tests") && c.Bool("tests") {
return fmt.Errorf("Both --with-tests and --tests cannot be set at the same time")
}
pkgs, err := collector.CollectProjectDeps(c.Bool("all-deps"), c.Bool("skip-self"), c.Bool("with-tests"), c.Bool("tests"))
if err != nil {
return err
}
sort.Strings(pkgs)
for _, item := range pkgs {
err := tmpl.Execute(os.Stdout, item)
if err != nil {
return err
}
}
return nil
}
if c.Bool("to-install") {
pkgs, err := collector.CollectInstalledResources()
if err != nil {
return err
}
sort.Strings(pkgs)
for _, item := range pkgs {
err := tmpl.Execute(os.Stdout, item)
if err != nil {
return err
}
}
return nil
}
return nil
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}