2020-05-04 19:00:53 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
// The "implements" tool uses code analysis and the conventions of the go-ceph
|
|
|
|
// project to produce a report comparing what go-ceph implements and what
|
|
|
|
// exists in the C ceph APIs. Only (lib)cephfs, (lib)rados, and (lib)rbd are
|
|
|
|
// and the equilvaent go-ceph packages are supported.
|
|
|
|
//
|
|
|
|
// Examples:
|
|
|
|
// # generate a full report on cephfs with a function listing
|
|
|
|
// ./implements --list ./cephfs
|
|
|
|
//
|
|
|
|
// # generate a brief summary on all packages
|
|
|
|
// ./implements ./cephfs ./rados ./rbd
|
|
|
|
//
|
|
|
|
// # generate a comprehensive report on rbd in json
|
2020-05-08 14:27:42 +00:00
|
|
|
// ./implements --list --json rbd
|
2020-05-04 19:00:53 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
2022-04-11 20:59:09 +00:00
|
|
|
"implements/internal/implements"
|
2020-05-04 19:00:53 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
verbose bool
|
|
|
|
list bool
|
|
|
|
reportJSON bool
|
2020-05-20 17:15:26 +00:00
|
|
|
outputJSON string
|
|
|
|
outputText string
|
2020-05-04 19:00:53 +00:00
|
|
|
|
|
|
|
// verbose logger
|
|
|
|
logger = log.New(os.Stderr, "(implements/verbose) ", log.LstdFlags)
|
|
|
|
)
|
|
|
|
|
|
|
|
func abort(msg string) {
|
|
|
|
log.Fatalf("error: %v\n", msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
flag.BoolVar(&verbose, "verbose", false, "be more verbose (for debugging)")
|
|
|
|
flag.BoolVar(&list, "list", false, "list functions")
|
2020-05-20 17:15:26 +00:00
|
|
|
flag.BoolVar(&reportJSON, "json", false,
|
|
|
|
"use JSON output format (this is a shortcut for '--report-json -')")
|
|
|
|
|
|
|
|
flag.StringVar(&outputJSON, "report-json", "", "filename for JSON report")
|
|
|
|
flag.StringVar(&outputText, "report-text", "", "filename for plain-text report")
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|
|
|
|
|
2021-09-21 18:45:28 +00:00
|
|
|
// TODO: this is a stub implementation that doesn't do anything.
|
|
|
|
// the intent is to eventually be able to tell a go-ceph sub-package
|
|
|
|
// like "rbd" or "cephfs/admin" apart from a real path like "/home/foo/go-ceph/rbd".
|
|
|
|
func splitPkg(s string) (string, string) {
|
|
|
|
return "", s
|
|
|
|
}
|
|
|
|
|
2020-05-04 19:00:53 +00:00
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
args := flag.Args()
|
|
|
|
if len(args) < 1 {
|
|
|
|
abort("missing package(s) to analyze")
|
|
|
|
}
|
|
|
|
if verbose {
|
|
|
|
implements.SetLogger(logger)
|
|
|
|
}
|
|
|
|
|
2020-05-20 17:15:26 +00:00
|
|
|
rpts := []implements.Reporter{}
|
2020-05-08 14:27:42 +00:00
|
|
|
// always annotate for now, leave the option of disabling it someday if it
|
|
|
|
// gets costly
|
2020-05-04 19:00:53 +00:00
|
|
|
o := implements.ReportOptions{
|
|
|
|
List: list,
|
2020-05-08 14:27:42 +00:00
|
|
|
Annotate: true,
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|
|
|
|
switch {
|
|
|
|
case reportJSON:
|
2020-05-20 17:15:26 +00:00
|
|
|
rpts = append(rpts, implements.NewJSONReport(o, os.Stdout))
|
|
|
|
case outputJSON == "-":
|
|
|
|
rpts = append(rpts, implements.NewJSONReport(o, os.Stdout))
|
|
|
|
case outputJSON != "":
|
|
|
|
f, err := os.Create(outputJSON)
|
|
|
|
if err != nil {
|
|
|
|
abort(err.Error())
|
|
|
|
}
|
2021-10-07 03:36:06 +00:00
|
|
|
defer func() { _ = f.Close() }()
|
2020-05-20 17:15:26 +00:00
|
|
|
rpts = append(rpts, implements.NewJSONReport(o, f))
|
|
|
|
}
|
|
|
|
switch {
|
|
|
|
case outputText == "-":
|
|
|
|
rpts = append(rpts, implements.NewTextReport(o, os.Stdout))
|
|
|
|
case outputText != "":
|
|
|
|
f, err := os.Create(outputText)
|
|
|
|
if err != nil {
|
|
|
|
abort(err.Error())
|
|
|
|
}
|
2021-10-07 03:36:06 +00:00
|
|
|
defer func() { _ = f.Close() }()
|
2020-05-20 17:15:26 +00:00
|
|
|
rpts = append(rpts, implements.NewTextReport(o, f))
|
|
|
|
}
|
|
|
|
if len(rpts) == 0 {
|
|
|
|
// no report types were explicitly selected. Use text report to stdout.
|
|
|
|
rpts = append(rpts, implements.NewTextReport(o, os.Stdout))
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, pkgref := range args[0:] {
|
2021-09-21 18:45:28 +00:00
|
|
|
source, pkg := splitPkg(pkgref)
|
|
|
|
checkCLang := false
|
2020-05-04 19:00:53 +00:00
|
|
|
switch pkg {
|
|
|
|
case "cephfs", "rados", "rbd":
|
2021-09-21 18:45:28 +00:00
|
|
|
checkCLang = true
|
|
|
|
if verbose {
|
|
|
|
logger.Printf("Processing package (with C): %s\n", pkg)
|
|
|
|
}
|
2022-04-11 20:59:09 +00:00
|
|
|
default:
|
2020-05-04 19:00:53 +00:00
|
|
|
if verbose {
|
|
|
|
logger.Printf("Processing package: %s\n", pkg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if source == "" {
|
|
|
|
source = "."
|
|
|
|
}
|
|
|
|
ii := implements.NewInspector()
|
2021-09-21 18:45:28 +00:00
|
|
|
if checkCLang {
|
|
|
|
if err := implements.CephCFunctions(pkg, ii); err != nil {
|
|
|
|
abort(err.Error())
|
|
|
|
}
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|
|
|
|
if err := implements.CephGoFunctions(source, pkg, ii); err != nil {
|
|
|
|
abort(err.Error())
|
|
|
|
}
|
2020-05-20 17:15:26 +00:00
|
|
|
for _, r := range rpts {
|
|
|
|
if err := r.Report(pkg, ii); err != nil {
|
|
|
|
abort(err.Error())
|
|
|
|
}
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-20 17:15:26 +00:00
|
|
|
for _, r := range rpts {
|
2021-10-07 03:36:06 +00:00
|
|
|
_ = r.Done()
|
2020-05-20 17:15:26 +00:00
|
|
|
}
|
2020-05-04 19:00:53 +00:00
|
|
|
}
|