Exemple #1
0
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
}
Exemple #2
0
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}})))
}
Exemple #3
0
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
}
Exemple #4
0
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)),
	}
}
Exemple #5
0
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
}
Exemple #6
0
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
}
Exemple #7
0
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
}
Exemple #8
0
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
}
Exemple #9
0
func (r *GraphUnitRule) Target() string {
	return filepath.ToSlash(filepath.Join(r.dataDir, plan.SourceUnitDataFilename(&graph.Output{}, r.Unit)))
}
Exemple #10
0
func (r *ResolveDepsRule) Prereqs() []string {
	return []string{filepath.Join(r.dataDir, plan.SourceUnitDataFilename(unit.SourceUnit{}, r.Unit))}
}
Exemple #11
0
func (r *ResolveDepsRule) Target() string {
	return filepath.Join(r.dataDir, plan.SourceUnitDataFilename([]*ResolvedDep{}, r.Unit))
}
Exemple #12
0
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
}
Exemple #13
0
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
}