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 *ToolchainBuildCmd) Execute(args []string) error {
	var wg sync.WaitGroup
	for _, tc := range c.Args.Toolchains {
		tc, err := toolchain.Open(string(tc), toolchain.AsDockerContainer)
		if err != nil {
			log.Fatal(err)
		}
		wg.Add(1)
		go func() {
			defer wg.Done()
			if err := tc.Build(); err != nil {
				log.Fatal(err)
			}
		}()
	}
	wg.Wait()
	return nil
}