func (r *GraphMultiUnitsRule) Targets() map[string]*unit.SourceUnit { targets := make(map[string]*unit.SourceUnit) for _, u := range r.Units { targets[filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(&graph.Output{}, u)))] = u } return targets }
func (r *GraphMultiUnitsRule) Target() string { // This is a dummy target, which is only used for ensuring a stable ordering of // the makefile rules (see plan/util.go). Both import command and coverage command // call the Targets() method to get the *.graph.json filepaths for all units graphed // by this rule. return filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(&graph.Output{}, &unit.SourceUnit{Key: unit.Key{Type: r.UnitsType}}))) }
func (r *GraphUnitRule) Prereqs() []string { ps := []string{filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(unit.SourceUnit{}, r.Unit)))} for _, file := range r.Unit.Files { if _, err := os.Stat(file); err != nil && os.IsNotExist(err) { // skip not-existent files listed in source unit continue } ps = append(ps, file) } return ps }
func (r *GraphMultiUnitsRule) Recipes() []string { if r.Tool == nil { return nil } safeCommand := util.SafeCommandName(srclib.CommandName) unitFiles := []string{} for _, u := range r.Units { unitFiles = append(unitFiles, filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(unit.SourceUnit{}, u)))) } // Use `find` command + `xargs` because otherwise the arguments list can become too long. var findCmd = "find -L" if runtime.GOOS == "windows" { findCmd = "/usr/bin/find" } return []string{ fmt.Sprintf(`%s %s -name "*%s.unit.json" | xargs %s internal emit-unit-data | %s tool %q %q | %s internal normalize-graph-data --unit-type %q --dir . --multi --data-dir %s`, findCmd, filepath.ToSlash(r.dataDir), r.UnitsType, safeCommand, safeCommand, r.Tool.Toolchain, r.Tool.Subcmd, safeCommand, r.UnitsType, filepath.ToSlash(r.dataDir)), } }
func (c *ConfigCmd) Execute(args []string) error { if c.w == nil { c.w = os.Stdout } if c.Quiet { c.w = nopWriteCloser{} } cfg, err := getInitialConfig(c.Options, c.Args.Dir.String()) if err != nil { return err } if len(cfg.PreConfigCommands) > 0 { if err := runPreConfigCommands(c.Args.Dir.String(), cfg.PreConfigCommands, c.ToolchainExecOpt, c.Quiet); err != nil { return fmt.Errorf("PreConfigCommands: %s", err) } } if err := scanUnitsIntoConfig(cfg, c.Options, c.ToolchainExecOpt, c.Quiet); err != nil { return fmt.Errorf("failed to scan for source units: %s", err) } localRepo, err := OpenRepo(c.Args.Dir.String()) if err != nil { return fmt.Errorf("failed to open repo: %s", err) } buildStore, err := buildstore.LocalRepo(localRepo.RootDir) if err != nil { return err } commitFS := buildStore.Commit(localRepo.CommitID) // Write source units to build cache. if err := rwvfs.MkdirAll(commitFS, "."); err != nil { return err } for _, u := range cfg.SourceUnits { unitFile := plan.SourceUnitDataFilename(unit.SourceUnit{}, u) if err := rwvfs.MkdirAll(commitFS, filepath.Dir(unitFile)); err != nil { return err } f, err := commitFS.Create(unitFile) if err != nil { return err } defer f.Close() if err := json.NewEncoder(f).Encode(u); err != nil { return err } if err := f.Close(); err != nil { log.Fatal(err) } } if c.Output.Output == "json" { PrintJSON(cfg, "") } else { fmt.Fprintf(c.w, "SCANNERS (%d)\n", len(cfg.Scanners)) for _, s := range cfg.Scanners { fmt.Fprintf(c.w, " - %s\n", s) } fmt.Fprintln(c.w) fmt.Fprintf(c.w, "SOURCE UNITS (%d)\n", len(cfg.SourceUnits)) for _, u := range cfg.SourceUnits { fmt.Fprintf(c.w, " - %s: %s\n", u.Type, u.Name) } fmt.Fprintln(c.w) fmt.Fprintf(c.w, "CONFIG PROPERTIES (%d)\n", len(cfg.Config)) for _, kv := range sortedMap(cfg.Config) { fmt.Fprintf(c.w, " - %s: %s\n", kv[0], kv[1]) } } return nil }
func (c *APIDescribeCmd) Execute(args []string) error { context, err := prepareCommandContext(c.File) if err != nil { return err } file := context.relativeFile units, err := getSourceUnitsWithFile(context.buildStore, context.repo, file) if err != nil { return err } if GlobalOpt.Verbose { if len(units) > 0 { ids := make([]string, len(units)) for i, u := range units { ids[i] = string(u.ID()) } log.Printf("Position %s:%d is in %d source units %v.", file, c.StartByte, len(units), ids) } else { log.Printf("Position %s:%d is not in any source units.", file, c.StartByte) } } // Find the ref(s) at the character position. var ref *graph.Ref var nearbyRefs []*graph.Ref // Find nearby refs to help with debugging. OuterLoop: for _, u := range units { var g graph.Output graphFile := plan.SourceUnitDataFilename("graph", u) f, err := context.commitFS.Open(graphFile) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&g); err != nil { return fmt.Errorf("%s: %s", graphFile, err) } for _, ref2 := range g.Refs { if file == ref2.File { if c.StartByte >= ref2.Start && c.StartByte <= ref2.End { ref = ref2 if ref.DefUnit == "" { ref.DefUnit = u.Name } if ref.DefUnitType == "" { ref.DefUnitType = u.Type } break OuterLoop } else if GlobalOpt.Verbose && abs(int(ref2.Start)-int(c.StartByte)) < 25 { nearbyRefs = append(nearbyRefs, ref2) } } } } if ref == nil { if GlobalOpt.Verbose { log.Printf("No ref found at %s:%d.", file, c.StartByte) if len(nearbyRefs) > 0 { log.Printf("However, nearby refs were found in the same file:") for _, nref := range nearbyRefs { log.Printf("Ref at bytes %d-%d to %v", nref.Start, nref.End, nref.DefKey()) } } f, err := os.Open(file) if err == nil { defer f.Close() b, err := ioutil.ReadAll(f) if err != nil { log.Fatalf("Error reading source file: %s.", err) } start := c.StartByte if start < 0 || int(start) > len(b)-1 { log.Fatalf("Start byte %d is out of file bounds.", c.StartByte) } end := c.StartByte + 50 if int(end) > len(b)-1 { end = uint32(len(b) - 1) } log.Printf("Surrounding source is:\n\n%s", b[start:end]) } else { log.Printf("Error opening source file to show surrounding source: %s.", err) } } fmt.Println(`{}`) return nil } // ref.DefRepo is *not* guaranteed to be non-empty, as // repo.URI() will return the empty string if the repo's // CloneURL is empty or malformed. if ref.DefRepo == "" { ref.DefRepo = context.repo.URI() } var resp apiDescribeCmdOutput // Now find the def for this ref. defInCurrentRepo := ref.DefRepo == context.repo.URI() if defInCurrentRepo { // Def is in the current repo. var g graph.Output graphFile := plan.SourceUnitDataFilename("graph", &unit.SourceUnit{Name: ref.DefUnit, Type: ref.DefUnitType}) f, err := context.commitFS.Open(graphFile) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&g); err != nil { return fmt.Errorf("%s: %s", graphFile, err) } for _, def2 := range g.Defs { if def2.Path == ref.DefPath { resp.Def = &sourcegraph.Def{Def: *def2} break } } if resp.Def != nil { for _, doc := range g.Docs { if doc.Path == ref.DefPath { resp.Def.DocHTML = doc.Data } } // If Def is in the current Repo, transform that path to be an absolute path resp.Def.File = filepath.Join(context.repo.RootDir, resp.Def.File) } if resp.Def == nil && GlobalOpt.Verbose { log.Printf("No definition found with path %q in unit %q type %q.", ref.DefPath, ref.DefUnit, ref.DefUnitType) } } // spec is only valid for remote requests if ref.DefRepo is // non-empty. var spec sourcegraph.DefSpec var specValid bool if ref.DefRepo != "" { specValid = true spec = sourcegraph.DefSpec{ Repo: string(ref.DefRepo), UnitType: ref.DefUnitType, Unit: ref.DefUnit, Path: string(ref.DefPath), } } if specValid { apiclient := NewAPIClientWithAuthIfPresent() var wg sync.WaitGroup if resp.Def == nil { // Def is not in the current repo. Try looking it up using the // Sourcegraph API. wg.Add(1) go func() { defer wg.Done() var err error resp.Def, _, err = apiclient.Defs.Get(spec, &sourcegraph.DefGetOptions{Doc: true}) if err != nil && GlobalOpt.Verbose { log.Printf("Couldn't fetch definition %v: %s.", spec, err) } }() } if !c.NoExamples { wg.Add(1) go func() { defer wg.Done() var err error resp.Examples, _, err = apiclient.Defs.ListExamples(spec, &sourcegraph.DefListExamplesOptions{ Formatted: true, ListOptions: sourcegraph.ListOptions{PerPage: 4}, }) if err != nil && GlobalOpt.Verbose { log.Printf("Couldn't fetch examples for %v: %s.", spec, err) } }() } wg.Wait() } if err := json.NewEncoder(os.Stdout).Encode(resp); err != nil { return err } return nil }
func (c *APIListCmd) Execute(args []string) error { context, err := prepareCommandContext(c.File) if err != nil { return err } file := context.relativeFile units, err := getSourceUnitsWithFile(context.buildStore, context.repo, file) if err != nil { return err } if GlobalOpt.Verbose { if len(units) > 0 { ids := make([]string, len(units)) for i, u := range units { ids[i] = string(u.ID()) } log.Printf("File %s is in %d source units %v.", file, len(units), ids) } else { log.Printf("File %s is not in any source units.", file) } } // Grab all the data for the file. var output apiListCmdOutput for _, u := range units { var g graph.Output graphFile := plan.SourceUnitDataFilename("graph", u) f, err := context.commitFS.Open(graphFile) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&g); err != nil { return fmt.Errorf("%s: %s", graphFile, err) } if !c.NoRefs { for _, ref := range g.Refs { if file == ref.File { output.Refs = append(output.Refs, ref) } } } if !c.NoDefs { for _, def := range g.Defs { if file == def.File { output.Defs = append(output.Defs, def) } } } if !c.NoDocs { for _, doc := range g.Docs { if file == doc.File { output.Docs = append(output.Docs, doc) } } } } if err := json.NewEncoder(os.Stdout).Encode(output); err != nil { return err } return nil }
func (r *GraphUnitRule) Prereqs() []string { ps := []string{filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(unit.SourceUnit{}, r.Unit)))} ps = append(ps, r.Unit.Files...) return ps }
func (r *GraphUnitRule) Target() string { return filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(&graph.Output{}, r.Unit))) }
func (r *ResolveDepsRule) Prereqs() []string { return []string{filepath.Join(r.dataDir, plan.SourceUnitDataFilename(unit.SourceUnit{}, r.Unit))} }
func (r *ResolveDepsRule) Target() string { return filepath.Join(r.dataDir, plan.SourceUnitDataFilename([]*ResolvedDep{}, r.Unit)) }
func (c *NormalizeGraphDataCmd) Execute(args []string) error { in := os.Stdin var o *graph.Output if err := json.NewDecoder(in).Decode(&o); err != nil { return err } if !c.Multi { if err := grapher.NormalizeData(c.UnitType, c.Dir, o); err != nil { return err } data, err := json.MarshalIndent(o, "", " ") if err != nil { return err } if _, err := os.Stdout.Write(data); err != nil { return err } return nil } // If `graph` emits multiple source units, in this case, don't // write to stdout (the rule will not direct it to a file), but // instead write to multiple .graph.json files (one for each // source unit). This is a HACK. // graphPerUnit maps source unit names to the graph data of // that unit. graphPerUnit := make(map[string]*graph.Output) initUnitGraph := func(unitName string) { if _, ok := graphPerUnit[unitName]; !ok { graphPerUnit[unitName] = &graph.Output{} } } // Split the graph data per source unit. for _, d := range o.Defs { if d.Unit == "" { log.Printf("skip def with empty unit: %v", d) continue } initUnitGraph(d.Unit) graphPerUnit[d.Unit].Defs = append(graphPerUnit[d.Unit].Defs, d) } for _, r := range o.Refs { if r.Unit == "" { log.Printf("skip ref with empty unit: %v", r) continue } initUnitGraph(r.Unit) graphPerUnit[r.Unit].Refs = append(graphPerUnit[r.Unit].Refs, r) } for _, d := range o.Docs { if d.DocUnit == "" { log.Printf("skip doc with empty unit: %v", d) continue } initUnitGraph(d.DocUnit) graphPerUnit[d.DocUnit].Docs = append(graphPerUnit[d.DocUnit].Docs, d) } for _, a := range o.Anns { if a.Unit == "" { log.Printf("skip ann with empty unit: %v", a) continue } initUnitGraph(a.Unit) graphPerUnit[a.Unit].Anns = append(graphPerUnit[a.Unit].Anns, a) } // Write the graph data to a separate file for each source unit. for unitName, graphData := range graphPerUnit { if err := grapher.NormalizeData(c.UnitType, c.Dir, graphData); err != nil { log.Printf("skipping unit %s because failed to normalize data: %s", unitName, err) continue } path := filepath.ToSlash(filepath.Join(c.DataDir, plan.SourceUnitDataFilename(&graph.Output{}, &unit.SourceUnit{Key: unit.Key{Name: unitName, Type: c.UnitType}}))) graphFile, err := os.Create(path) if err != nil { return err } data, err := json.MarshalIndent(graphData, "", " ") if err != nil { return err } if _, err := graphFile.Write(data); err != nil { return err } } return nil }
func (c *APIDescribeCmd) Execute(args []string) error { context, err := prepareCommandContext(c.File) if err != nil { return err } file := context.relativeFile units, err := getSourceUnitsWithFile(context.buildStore, context.repo, file) if err != nil { return err } if GlobalOpt.Verbose { if len(units) > 0 { ids := make([]string, len(units)) for i, u := range units { ids[i] = string(u.ID()) } log.Printf("Position %s:%d is in %d source units %v.", file, c.StartByte, len(units), ids) } else { log.Printf("Position %s:%d is not in any source units.", file, c.StartByte) } } // Find the ref(s) at the character position. var ref *graph.Ref var nearbyRefs []*graph.Ref // Find nearby refs to help with debugging. OuterLoop: for _, u := range units { var g graph.Output graphFile := plan.SourceUnitDataFilename("graph", u) f, err := context.commitFS.Open(graphFile) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&g); err != nil { return fmt.Errorf("%s: %s", graphFile, err) } for _, ref2 := range g.Refs { if file == ref2.File { if c.StartByte >= ref2.Start && c.StartByte <= ref2.End { ref = ref2 if ref.DefUnit == "" { ref.DefUnit = u.Name } if ref.DefUnitType == "" { ref.DefUnitType = u.Type } break OuterLoop } else if GlobalOpt.Verbose && abs(int(ref2.Start)-int(c.StartByte)) < 25 { nearbyRefs = append(nearbyRefs, ref2) } } } } if ref == nil { if GlobalOpt.Verbose { log.Printf("No ref found at %s:%d.", file, c.StartByte) if len(nearbyRefs) > 0 { log.Printf("However, nearby refs were found in the same file:") for _, nref := range nearbyRefs { log.Printf("Ref at bytes %d-%d to %v", nref.Start, nref.End, nref.DefKey()) } } f, err := os.Open(file) if err == nil { defer f.Close() b, err := ioutil.ReadAll(f) if err != nil { log.Fatalf("Error reading source file: %s.", err) } start := c.StartByte if start < 0 || int(start) > len(b)-1 { log.Fatalf("Start byte %d is out of file bounds.", c.StartByte) } end := c.StartByte + 50 if int(end) > len(b)-1 { end = uint32(len(b) - 1) } log.Printf("Surrounding source is:\n\n%s", b[start:end]) } else { log.Printf("Error opening source file to show surrounding source: %s.", err) } } colorable.Println(`{}`) return nil } var resp apiDescribeCmdOutput // Now find the def for this ref. defInCurrentRepo := ref.DefRepo == "" if defInCurrentRepo { // Def is in the current repo. var g graph.Output graphFile := plan.SourceUnitDataFilename("graph", &unit.SourceUnit{Name: ref.DefUnit, Type: ref.DefUnitType}) f, err := context.commitFS.Open(graphFile) if err != nil { return err } defer f.Close() if err := json.NewDecoder(f).Decode(&g); err != nil { return fmt.Errorf("%s: %s", graphFile, err) } for _, def := range g.Defs { if def.Path == ref.DefPath { resp.Def = def break } } if resp.Def != nil { // If Def is in the current Repo, transform that path to be an absolute path resp.Def.File = filepath.ToSlash(filepath.Join(context.repo.RootDir, resp.Def.File)) } if resp.Def == nil && GlobalOpt.Verbose { log.Printf("No definition found with path %q in unit %q type %q.", ref.DefPath, ref.DefUnit, ref.DefUnitType) } } if err := json.NewEncoder(os.Stdout).Encode(resp); err != nil { return err } return nil }