github.com/tiagovtristao/plz@v13.4.0+incompatible/tools/please_maven/main.go (about)

     1  // Package main implements please_maven, a command-line tool to find dependencies
     2  // from a remote Maven repo (typically Maven Central, but can be others).
     3  //
     4  // This is a fairly non-trivial task since the pom.xml format is complex and
     5  // Maven is basically just a static file server for them. We do our best at
     6  // understanding it.
     7  // Of course other packages exist that can parse it, but we prefer not to use them
     8  // since they're Java, and would require shipping a very large binary, but
     9  // more significantly it did not seem easy to make them behave as we wanted.
    10  package main
    11  
    12  import (
    13  	"encoding/json"
    14  	"fmt"
    15  	"io"
    16  	"os"
    17  	"strings"
    18  
    19  	"github.com/thought-machine/please/src/cli"
    20  	"github.com/thought-machine/please/tools/please_maven/maven"
    21  )
    22  
    23  var opts = struct {
    24  	Usage        string
    25  	Verbosity    cli.Verbosity `short:"v" long:"verbosity" default:"warning" description:"Verbosity of output (higher number = more output)"`
    26  	Repositories []string      `short:"r" long:"repository" description:"Location of Maven repo" default:"https://repo1.maven.org/maven2"`
    27  	Android      bool          `short:"a" long:"android" description:"Adds https://maven.google.org to repositories for Android deps."`
    28  	Exclude      []string      `short:"e" long:"exclude" description:"Artifacts to exclude from download"`
    29  	Indent       bool          `short:"i" long:"indent" description:"Indent stdout lines appropriately"`
    30  	Optional     []string      `short:"o" long:"optional" description:"Optional dependencies to fetch"`
    31  	BuildRules   bool          `short:"b" long:"build_rules" description:"Print individual maven_jar build rules for each artifact"`
    32  	NumThreads   int           `short:"n" long:"num_threads" default:"10" description:"Number of concurrent fetches to perform"`
    33  	LicenceOnly  bool          `short:"l" long:"licence_only" description:"Fetch only the licence of the given package from Maven"`
    34  	Graph        string        `short:"g" long:"graph" description:"Graph file, as exported from plz query graph. If given then existing dependencies in it will be integrated when using --build_rules."`
    35  	Args         struct {
    36  		Artifacts []maven.Artifact `positional-arg-name:"ids" required:"yes" description:"Maven IDs to fetch (e.g. io.grpc:grpc-all:1.4.0)"`
    37  	} `positional-args:"yes" required:"yes"`
    38  }{
    39  	Usage: `
    40  please_maven is a tool shipped with Please that communicates with Maven repositories
    41  to work out what files to download given a package spec.
    42  
    43  Example usage:
    44  please_maven io.grpc:grpc-all:1.1.2
    45  > io.grpc:grpc-auth:1.1.2:src:BSD 3-Clause
    46  > io.grpc:grpc-core:1.1.2:src:BSD 3-Clause
    47  > ...
    48  Its output is similarly in the common Maven artifact format which can be used to create
    49  maven_jar rules in BUILD files. It also outputs some notes on whether sources are
    50  available and what licence the package is under, if it can find it.
    51  
    52  Note that it does not do complex cross-package dependency resolution and doesn't
    53  necessarily support every aspect of Maven's pom.xml format, which is pretty hard
    54  to fully grok. The goal is to provide a backend to Please's built-in maven_jars
    55  rule to make adding dependencies easier.
    56  `,
    57  }
    58  
    59  func loadGraph(filename string) *maven.Graph {
    60  	if filename == "" {
    61  		return &maven.Graph{}
    62  	} else if filename == "-" {
    63  		return decodeGraph(os.Stdin) // Read from stdin.
    64  	}
    65  	f, err := os.Open(filename)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	defer f.Close()
    70  	return decodeGraph(f)
    71  }
    72  
    73  func decodeGraph(r io.Reader) *maven.Graph {
    74  	g := &maven.Graph{}
    75  	if err := json.NewDecoder(r).Decode(g); err != nil {
    76  		panic(err)
    77  	}
    78  	return g
    79  }
    80  
    81  func main() {
    82  	cli.ParseFlagsOrDie("please_maven", &opts)
    83  	cli.InitLogging(opts.Verbosity)
    84  	if opts.Android {
    85  		opts.Repositories = append(opts.Repositories, "https://maven.google.com")
    86  	}
    87  	f := maven.NewFetch(opts.Repositories, opts.Exclude, opts.Optional)
    88  	if opts.LicenceOnly {
    89  		for _, artifact := range opts.Args.Artifacts {
    90  			for _, licence := range f.Pom(&artifact).Licences.Licence {
    91  				fmt.Println(licence.Name)
    92  			}
    93  		}
    94  	} else {
    95  		fmt.Println(strings.Join(maven.AllDependencies(f, opts.Args.Artifacts, opts.NumThreads, opts.Indent, opts.BuildRules, loadGraph(opts.Graph)), "\n"))
    96  	}
    97  }