Loading tools/compliance/Android.bp +27 −6 Original line number Diff line number Diff line Loading @@ -20,14 +20,20 @@ package { blueprint_go_binary { name: "compliance_checkshare", srcs: ["cmd/checkshare/checkshare.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/checkshare/checkshare_test.go"], } blueprint_go_binary { name: "compliancenotice_bom", srcs: ["cmd/bom/bom.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/bom/bom_test.go"], } Loading @@ -44,21 +50,30 @@ blueprint_go_binary { blueprint_go_binary { name: "compliance_listshare", srcs: ["cmd/listshare/listshare.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/listshare/listshare_test.go"], } blueprint_go_binary { name: "compliance_dumpgraph", srcs: ["cmd/dumpgraph/dumpgraph.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/dumpgraph/dumpgraph_test.go"], } blueprint_go_binary { name: "compliance_dumpresolutions", srcs: ["cmd/dumpresolutions/dumpresolutions.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/dumpresolutions/dumpresolutions_test.go"], } Loading @@ -68,6 +83,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/htmlnotice/htmlnotice_test.go"], } Loading @@ -75,7 +91,10 @@ blueprint_go_binary { blueprint_go_binary { name: "compliance_rtrace", srcs: ["cmd/rtrace/rtrace.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/rtrace/rtrace_test.go"], } Loading @@ -85,6 +104,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/textnotice/textnotice_test.go"], } Loading @@ -95,6 +115,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/xmlnotice/xmlnotice_test.go"], } Loading tools/compliance/cmd/bom/bom.go +45 −23 Original line number Diff line number Diff line Loading @@ -24,13 +24,11 @@ import ( "path/filepath" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( outputFile = flag.String("o", "-", "Where to write the bill of materials. (default stdout)") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -55,22 +53,10 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a bill of materials. i.e. the list of installed paths. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) flags.Var(&f, name, usage) return &f } Loading @@ -81,16 +67,52 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { flag.Parse() var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a bill of materials. i.e. the list of installed paths. Options: `, filepath.Base(os.Args[0])) flags.PrintDefaults() } outputFile := flags.String("o", "-", "Where to write the bill of materials. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flag.Usage() flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { Loading Loading @@ -118,10 +140,10 @@ func main() { ctx := &context{ofile, os.Stderr, compliance.FS, *stripPrefix} err := billOfMaterials(ctx, flag.Args()...) err := billOfMaterials(ctx, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) Loading tools/compliance/cmd/checkshare/checkshare.go +86 −23 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -22,13 +23,51 @@ import ( "os" "path/filepath" "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...} var ( failConflicts = fmt.Errorf("conflicts") failNoneRequested = fmt.Errorf("\nNo metadata files requested") failNoLicenses = fmt.Errorf("No licenses") ) // byError orders conflicts by error string type byError []compliance.SourceSharePrivacyConflict func (l byError) Len() int { return len(l) } func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] } func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {-o outfile} file.meta_lic {file.meta_lic...} Reports on stderr any targets where policy says that the source both must and must not be shared. The error report indicates the target, the Loading @@ -44,41 +83,65 @@ outputs "PASS" to stdout and exits with status 0. If policy says any source must both be shared and not be shared, outputs "FAIL" to stdout and exits with status 1. `, filepath.Base(os.Args[0])) flags.PrintDefaults() } } var ( failConflicts = fmt.Errorf("conflicts") failNoneRequested = fmt.Errorf("\nNo metadata files requested") failNoLicenses = fmt.Errorf("No licenses") ) // byError orders conflicts by error string type byError []compliance.SourceSharePrivacyConflict func (l byError) Len() int { return len(l) } func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] } func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() } outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } err := checkShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...) err := checkShare(ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err != failConflicts { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) } os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading @@ -92,7 +155,7 @@ func checkShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error { // Read the license graph from the license metadata files (*.meta_lic). licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files) if err != nil { return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err) return fmt.Errorf("Unable to read license metadata file(s) %q from %q: %w\n", files, os.Getenv("PWD"), err) } if licenseGraph == nil { return failNoLicenses Loading tools/compliance/cmd/dumpgraph/dumpgraph.go +86 −26 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -24,14 +25,11 @@ import ( "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -55,8 +53,44 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { // newMultiString creates a flag that allows multiple values in an array. func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flags.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs space-separated Target Dependency Annotations tuples for each Loading @@ -70,42 +104,68 @@ target:condition1:condition2 etc. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } flags.PrintDefaults() } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.") outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } ctx := &context{*graphViz, *labelConditions, *stripPrefix} err := dumpGraph(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...) err := dumpGraph(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading tools/compliance/cmd/dumpresolutions/dumpresolutions.go +87 −27 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -24,15 +25,11 @@ import ( "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( conditions = newMultiString("c", "License condition to resolve. (may be given multiple times)") graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -57,8 +54,44 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { // newMultiString creates a flag that allows multiple values in an array. func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flags.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a space-separated Target ActsOn Origin Condition tuple for each Loading @@ -75,32 +108,52 @@ i.e. target:condition1:condition2 etc. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } flags.PrintDefaults() } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } conditions := newMultiString(flags, "c", "License condition to resolve. (may be given multiple times)") graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.") outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } lcs := make([]compliance.LicenseCondition, 0, len(*conditions)) for _, name := range *conditions { lcs = append(lcs, compliance.RecognizedConditionNames[name]) Loading @@ -111,14 +164,21 @@ func main() { labelConditions: *labelConditions, stripPrefix: *stripPrefix, } _, err := dumpResolutions(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...) _, err := dumpResolutions(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading Loading
tools/compliance/Android.bp +27 −6 Original line number Diff line number Diff line Loading @@ -20,14 +20,20 @@ package { blueprint_go_binary { name: "compliance_checkshare", srcs: ["cmd/checkshare/checkshare.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/checkshare/checkshare_test.go"], } blueprint_go_binary { name: "compliancenotice_bom", srcs: ["cmd/bom/bom.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/bom/bom_test.go"], } Loading @@ -44,21 +50,30 @@ blueprint_go_binary { blueprint_go_binary { name: "compliance_listshare", srcs: ["cmd/listshare/listshare.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/listshare/listshare_test.go"], } blueprint_go_binary { name: "compliance_dumpgraph", srcs: ["cmd/dumpgraph/dumpgraph.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/dumpgraph/dumpgraph_test.go"], } blueprint_go_binary { name: "compliance_dumpresolutions", srcs: ["cmd/dumpresolutions/dumpresolutions.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/dumpresolutions/dumpresolutions_test.go"], } Loading @@ -68,6 +83,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/htmlnotice/htmlnotice_test.go"], } Loading @@ -75,7 +91,10 @@ blueprint_go_binary { blueprint_go_binary { name: "compliance_rtrace", srcs: ["cmd/rtrace/rtrace.go"], deps: ["compliance-module"], deps: [ "compliance-module", "soong-response", ], testSrcs: ["cmd/rtrace/rtrace_test.go"], } Loading @@ -85,6 +104,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/textnotice/textnotice_test.go"], } Loading @@ -95,6 +115,7 @@ blueprint_go_binary { deps: [ "compliance-module", "blueprint-deptools", "soong-response", ], testSrcs: ["cmd/xmlnotice/xmlnotice_test.go"], } Loading
tools/compliance/cmd/bom/bom.go +45 −23 Original line number Diff line number Diff line Loading @@ -24,13 +24,11 @@ import ( "path/filepath" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( outputFile = flag.String("o", "-", "Where to write the bill of materials. (default stdout)") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -55,22 +53,10 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a bill of materials. i.e. the list of installed paths. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) flags.Var(&f, name, usage) return &f } Loading @@ -81,16 +67,52 @@ func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { flag.Parse() var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a bill of materials. i.e. the list of installed paths. Options: `, filepath.Base(os.Args[0])) flags.PrintDefaults() } outputFile := flags.String("o", "-", "Where to write the bill of materials. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flag.Usage() flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { Loading Loading @@ -118,10 +140,10 @@ func main() { ctx := &context{ofile, os.Stderr, compliance.FS, *stripPrefix} err := billOfMaterials(ctx, flag.Args()...) err := billOfMaterials(ctx, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) Loading
tools/compliance/cmd/checkshare/checkshare.go +86 −23 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -22,13 +23,51 @@ import ( "os" "path/filepath" "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) func init() { flag.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s file.meta_lic {file.meta_lic...} var ( failConflicts = fmt.Errorf("conflicts") failNoneRequested = fmt.Errorf("\nNo metadata files requested") failNoLicenses = fmt.Errorf("No licenses") ) // byError orders conflicts by error string type byError []compliance.SourceSharePrivacyConflict func (l byError) Len() int { return len(l) } func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] } func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {-o outfile} file.meta_lic {file.meta_lic...} Reports on stderr any targets where policy says that the source both must and must not be shared. The error report indicates the target, the Loading @@ -44,41 +83,65 @@ outputs "PASS" to stdout and exits with status 0. If policy says any source must both be shared and not be shared, outputs "FAIL" to stdout and exits with status 1. `, filepath.Base(os.Args[0])) flags.PrintDefaults() } } var ( failConflicts = fmt.Errorf("conflicts") failNoneRequested = fmt.Errorf("\nNo metadata files requested") failNoLicenses = fmt.Errorf("No licenses") ) // byError orders conflicts by error string type byError []compliance.SourceSharePrivacyConflict func (l byError) Len() int { return len(l) } func (l byError) Swap(i, j int) { l[i], l[j] = l[j], l[i] } func (l byError) Less(i, j int) bool { return l[i].Error() < l[j].Error() } outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } err := checkShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...) err := checkShare(ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err != failConflicts { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) } os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading @@ -92,7 +155,7 @@ func checkShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error { // Read the license graph from the license metadata files (*.meta_lic). licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files) if err != nil { return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err) return fmt.Errorf("Unable to read license metadata file(s) %q from %q: %w\n", files, os.Getenv("PWD"), err) } if licenseGraph == nil { return failNoLicenses Loading
tools/compliance/cmd/dumpgraph/dumpgraph.go +86 −26 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -24,14 +25,11 @@ import ( "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -55,8 +53,44 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { // newMultiString creates a flag that allows multiple values in an array. func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flags.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs space-separated Target Dependency Annotations tuples for each Loading @@ -70,42 +104,68 @@ target:condition1:condition2 etc. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } flags.PrintDefaults() } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.") outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } ctx := &context{*graphViz, *labelConditions, *stripPrefix} err := dumpGraph(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...) err := dumpGraph(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading
tools/compliance/cmd/dumpresolutions/dumpresolutions.go +87 −27 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package main import ( "bytes" "flag" "fmt" "io" Loading @@ -24,15 +25,11 @@ import ( "sort" "strings" "android/soong/response" "android/soong/tools/compliance" ) var ( conditions = newMultiString("c", "License condition to resolve. (may be given multiple times)") graphViz = flag.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions = flag.Bool("label_conditions", false, "Whether to label target nodes with conditions.") stripPrefix = newMultiString("strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") failNoneRequested = fmt.Errorf("\nNo license metadata files requested") failNoLicenses = fmt.Errorf("No licenses found") ) Loading @@ -57,8 +54,44 @@ func (ctx context) strip(installPath string) string { return installPath } func init() { flag.Usage = func() { // newMultiString creates a flag that allows multiple values in an array. func newMultiString(flags *flag.FlagSet, name, usage string) *multiString { var f multiString flags.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } func main() { var expandedArgs []string for _, arg := range os.Args[1:] { if strings.HasPrefix(arg, "@") { f, err := os.Open(strings.TrimPrefix(arg, "@")) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } respArgs, err := response.ReadRspFile(f) f.Close() if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } expandedArgs = append(expandedArgs, respArgs...) } else { expandedArgs = append(expandedArgs, arg) } } flags := flag.NewFlagSet("flags", flag.ExitOnError) flags.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...} Outputs a space-separated Target ActsOn Origin Condition tuple for each Loading @@ -75,32 +108,52 @@ i.e. target:condition1:condition2 etc. Options: `, filepath.Base(os.Args[0])) flag.PrintDefaults() } flags.PrintDefaults() } // newMultiString creates a flag that allows multiple values in an array. func newMultiString(name, usage string) *multiString { var f multiString flag.Var(&f, name, usage) return &f } // multiString implements the flag `Value` interface for multiple strings. type multiString []string func (ms *multiString) String() string { return strings.Join(*ms, ", ") } func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil } conditions := newMultiString(flags, "c", "License condition to resolve. (may be given multiple times)") graphViz := flags.Bool("dot", false, "Whether to output graphviz (i.e. dot) format.") labelConditions := flags.Bool("label_conditions", false, "Whether to label target nodes with conditions.") outputFile := flags.String("o", "-", "Where to write the output. (default stdout)") stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)") func main() { flag.Parse() flags.Parse(expandedArgs) // Must specify at least one root target. if flag.NArg() == 0 { flag.Usage() if flags.NArg() == 0 { flags.Usage() os.Exit(2) } if len(*outputFile) == 0 { flags.Usage() fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n") os.Exit(2) } else { dir, err := filepath.Abs(filepath.Dir(*outputFile)) if err != nil { fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err) os.Exit(1) } fi, err := os.Stat(dir) if err != nil { fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err) os.Exit(1) } if !fi.IsDir() { fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile) os.Exit(1) } } var ofile io.Writer ofile = os.Stdout var obuf *bytes.Buffer if *outputFile != "-" { obuf = &bytes.Buffer{} ofile = obuf } lcs := make([]compliance.LicenseCondition, 0, len(*conditions)) for _, name := range *conditions { lcs = append(lcs, compliance.RecognizedConditionNames[name]) Loading @@ -111,14 +164,21 @@ func main() { labelConditions: *labelConditions, stripPrefix: *stripPrefix, } _, err := dumpResolutions(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...) _, err := dumpResolutions(ctx, ofile, os.Stderr, compliance.FS, flags.Args()...) if err != nil { if err == failNoneRequested { flag.Usage() flags.Usage() } fmt.Fprintf(os.Stderr, "%s\n", err.Error()) os.Exit(1) } if *outputFile != "-" { err := os.WriteFile(*outputFile, obuf.Bytes(), 0666) if err != nil { fmt.Fprintf(os.Stderr, "could not write output to %q from %q: %s\n", *outputFile, os.Getenv("PWD"), err) os.Exit(1) } } os.Exit(0) } Loading