Example #1
0
func (c *ToolCmd) Execute(args []string) error {
	tc, err := toolchain.Open(string(c.Args.Toolchain), c.ToolchainMode())
	if err != nil {
		log.Fatal(err)
	}

	var cmder interface {
		Command() (*exec.Cmd, error)
	}
	if c.Args.Tool != "" {
		cmder, err = toolchain.OpenTool(string(c.Args.Toolchain), string(c.Args.Tool), c.ToolchainMode())
	} else {
		cmder = tc
	}

	// HACK: Buffer stdout to work around
	// https://github.com/docker/docker/issues/3631. Otherwise, lots
	// of builds fail. Also, if a lot of data is printed, the return
	// code is 0, but JSON parsing fails, retry it up to 4 times until
	// JSON parsing succeeds.
	for tries := 4; ; tries-- {
		cmd, err := cmder.Command()
		if err != nil {
			log.Fatal(err)
		}
		cmd.Args = append(cmd.Args, c.Args.ToolArgs...)
		cmd.Stderr = os.Stderr
		var out bytes.Buffer
		cmd.Stdout = &out
		cmd.Stdin = os.Stdin
		if GlobalOpt.Verbose {
			log.Printf("Running tool: %v", cmd.Args)
		}
		if err := cmd.Run(); err != nil {
			log.Fatal(err)
		}

		b := out.Bytes()

		if tries > 0 {
			// Try parsing (see HACK) above.
			if len(b) > 2000 {
				var o interface{}
				if err := json.Unmarshal(b, &o); err != nil {
					log.Printf("Suspect JSON output by %v (%d bytes, parse error %q); retrying %d more times. (This is a workaround for https://github.com/docker/docker/issues/3631.)", cmd.Args, len(b), err, tries)
					continue // retry
				}
			}
		}

		os.Stdout.Write(b)
		return nil
	}
}
Example #2
0
func (c *FmtCmd) Get() (string, error) {
	t, err := toolchain.ChooseTool(fmtOpt, c.UnitType)
	if err != nil {
		return "", err
	}
	// Only call as a program for now.
	tool, err := toolchain.OpenTool(t.Toolchain, t.Subcmd, toolchain.AsProgram)
	if err != nil {
		return "", err
	}
	cmd, err := tool.Command()
	if err != nil {
		return "", err
	}
	out := &bytes.Buffer{}
	cmd.Stdout = out
	cmd.Args = append(cmd.Args, "--unit-type", c.UnitType, "--object-type", c.ObjectType, "--format", c.Format, "--object", c.Object)
	if err := cmd.Run(); err != nil {
		return "", err
	}
	return out.String(), nil
}
Example #3
0
// scanUnitsIntoConfig uses cfg to scan for source units. It modifies
// cfg.SourceUnits, merging the scanned source units with those already present
// in cfg.
func scanUnitsIntoConfig(cfg *config.Repository, configOpt config.Options, execOpt ToolchainExecOpt, quiet bool) error {
	scanners := make([]toolchain.Tool, len(cfg.Scanners))
	for i, scannerRef := range cfg.Scanners {
		scanner, err := toolchain.OpenTool(scannerRef.Toolchain, scannerRef.Subcmd, execOpt.ToolchainMode())
		if err != nil {
			return err
		}
		scanners[i] = scanner
	}

	units, err := scan.ScanMulti(scanners, scan.Options{Options: configOpt, Quiet: quiet}, cfg.Config)
	if err != nil {
		return err
	}

	// Merge the repo/tree config with each source unit's config.
	if cfg.Config == nil {
		cfg.Config = map[string]interface{}{}
	}
	for _, u := range units {
		for k, v := range cfg.Config {
			if uv, present := u.Config[k]; present {
				log.Printf("Both the scanned source unit %q and the Srcfile specify a Config key %q. Using the value from the scanned source unit (%+v).", u.ID(), k, uv)
			} else {
				if u.Config == nil {
					u.Config = map[string]interface{}{}
				}
				u.Config[k] = v
			}
		}
	}

	// collect manually specified source units by ID
	manualUnits := make(map[unit.ID]*unit.SourceUnit, len(cfg.SourceUnits))
	for _, u := range cfg.SourceUnits {
		manualUnits[u.ID()] = u

		xf, err := unit.ExpandPaths(".", u.Files)
		if err != nil {
			return err
		}
		u.Files = xf
	}

	for _, u := range units {
		if mu, present := manualUnits[u.ID()]; present {
			log.Printf("Found manually specified source unit %q with same ID as scanned source unit. Using manually specified unit, ignoring scanned source unit.", mu.ID())
			continue
		}

		unitDir := u.Dir
		if unitDir == "" && len(u.Files) > 0 {
			// in case the unit doesn't specify a Dir, obtain it from the first file
			unitDir = filepath.Dir(u.Files[0])
		}

		// heed SkipDirs
		if pathHasAnyPrefix(unitDir, cfg.SkipDirs) {
			continue
		}

		skip := false
		for _, skipUnit := range cfg.SkipUnits {
			if u.Name == skipUnit.Name && u.Type == skipUnit.Type {
				skip = true
				break
			}
		}
		if skip {
			continue
		}

		cfg.SourceUnits = append(cfg.SourceUnits, u)
	}

	return nil
}