// Function retries the given function for the given number of // attempts at the given interval. func Function(ctx *tool.Context, fn func() error, opts ...RetryOpt) error { attempts, interval := defaultAttempts, defaultInterval for _, opt := range opts { switch typedOpt := opt.(type) { case AttemptsOpt: attempts = int(typedOpt) case IntervalOpt: interval = time.Duration(typedOpt) } } var err error for i := 1; i <= attempts; i++ { if i > 1 { fmt.Fprintf(ctx.Stdout(), "Attempt %d/%d:\n", i, attempts) } if err = fn(); err == nil { return nil } fmt.Fprintf(ctx.Stderr(), "%v\n", err) if i < attempts { fmt.Fprintf(ctx.Stdout(), "Wait for %v before next attempt...\n", interval) time.Sleep(interval) } } return fmt.Errorf("Failed %d times in a row. Last error:\n%v", attempts, err) }
// RunCommand runs the specified command with the specified args and environment // whilst logging the output to ctx.Stdout() on error or if tracing is requested // via the -v flag. func RunCommand(ctx *tool.Context, env map[string]string, bin string, args ...string) error { var out bytes.Buffer opts := ctx.Run().Opts() opts.Stdout = &out opts.Stderr = &out opts.Env = env err := ctx.Run().CommandWithOpts(opts, bin, args...) if err != nil || tool.VerboseFlag { fmt.Fprintf(ctx.Stdout(), "%s", out.String()) } return err }
// WARNING: this function is in the proces of being removed and replaced // by the profiles based configuration (see jiri/profiles). Use // profiles.ConfigHelper instead of this for new code. // // JiriLegacyEnvironment returns the environment variables setting for the project. // The util package captures the original state of the relevant environment // variables when the tool is initialized and every invocation of this function // updates this original state according to the jiri tool configuration. // // By default, the Go and VDL workspaces are added to the GOPATH and VDLPATH // environment variables respectively. In addition, the JIRI_PROFILE // environment variable can be used to activate an environment variable setting // for various development profiles of the project (e.g. arm, android, java, or // nacl). Unlike the default setting, the setting enabled by the JIRI_PROFILE // environment variable can override existing environment. func JiriLegacyEnvironment(ctx *tool.Context) (*envvar.Vars, error) { env := envvar.VarsFromOS() root, err := project.JiriRoot() if err != nil { return nil, err } config, err := LoadConfig(ctx) if err != nil { return nil, err } env.Set("CGO_ENABLED", "1") if err := setGoPath(ctx, env, root, config); err != nil { return nil, err } if err := setVdlPath(ctx, env, root, config); err != nil { return nil, err } if profile := os.Getenv(jiriProfileEnv); profile != "" { fmt.Fprintf(ctx.Stdout(), `NOTE: Enabling environment variable setting for %q. This can override values of existing environment variables. `, profile) switch profile { case "android": // Cross-compilation for android on linux. if err := setAndroidEnv(ctx, env, root); err != nil { return nil, err } case "arm": // Cross-compilation for arm on linux. if err := setArmEnv(ctx, env, root); err != nil { return nil, err } case "java": // Building of a Go shared library for Java. if err := setJavaEnv(ctx, env, root); err != nil { return nil, err } case "nacl": // Cross-compilation for nacl. if err := setNaclEnv(ctx, env, root); err != nil { return nil, err } default: fmt.Fprintf(ctx.Stderr(), "Unknown environment profile %q", profile) } } if err := setSyncbaseEnv(ctx, env, root); err != nil { return nil, err } return env, nil }
func brewList(ctx *tool.Context) (map[string]bool, error) { var out bytes.Buffer opts := ctx.Run().Opts() opts.Stdout = &out opts.Stderr = &out err := ctx.Run().CommandWithOpts(opts, "brew", "list") if err != nil || tool.VerboseFlag { fmt.Fprintf(ctx.Stdout(), "%s", out.String()) } scanner := bufio.NewScanner(&out) pkgs := map[string]bool{} for scanner.Scan() { pkgs[scanner.Text()] = true } return pkgs, err }
// EnsureProfileTargetIsUninstalled ensures that the requested profile and target // are no longer installed. func EnsureProfileTargetIsUninstalled(ctx *tool.Context, profile string, target Target, root string) error { if LookupProfileTarget(profile, target) != nil { if ctx.Run().Opts().Verbose { fmt.Fprintf(ctx.Stdout(), "%v is not installed: %v", profile, target) } return nil } mgr := LookupManager(profile) if mgr == nil { return fmt.Errorf("profile %v is not supported", profile) } mgr.SetRoot(root) if ctx.Run().Opts().Verbose || ctx.Run().Opts().DryRun { fmt.Fprintf(ctx.Stdout(), "uninstall %s %s\n", profile, target.DebugString()) } if err := mgr.Uninstall(ctx, target); err != nil { return err } return nil }
func logResult(ctx *tool.Context, action string, mgr profiles.Manager, target profiles.Target, err error) { fmt.Fprintf(ctx.Stdout(), "%s: %s %s: ", action, mgr.Name(), target) if err == nil { fmt.Fprintf(ctx.Stdout(), "success\n") } else { fmt.Fprintf(ctx.Stdout(), "%v\n", err) } }
// InstallPackages identifies the packages that need to be installed // and installs them using the OS-specific package manager. func InstallPackages(ctx *tool.Context, pkgs []string) error { installDepsFn := func() error { switch runtime.GOOS { case "linux": installPkgs := []string{} for _, pkg := range pkgs { if err := RunCommand(ctx, nil, "dpkg", "-L", pkg); err != nil { installPkgs = append(installPkgs, pkg) } } if len(installPkgs) > 0 { args := append([]string{"apt-get", "install", "-y"}, installPkgs...) fmt.Fprintf(ctx.Stdout(), "Running: sudo %s: ", strings.Join(args, " ")) if err := RunCommand(ctx, nil, "sudo", args...); err != nil { fmt.Fprintf(ctx.Stdout(), "%v\n", err) return err } fmt.Fprintf(ctx.Stdout(), "success\n") } case "darwin": installPkgs := []string{} installedPkgs, err := brewList(ctx) if err != nil { return err } for _, pkg := range pkgs { if !installedPkgs[pkg] { installPkgs = append(installPkgs, pkg) } } if len(installPkgs) > 0 { args := append([]string{"install"}, installPkgs...) fmt.Fprintf(ctx.Stdout(), "Running: brew %s: ", strings.Join(args, " ")) if err := RunCommand(ctx, nil, "brew", args...); err != nil { fmt.Fprintf(ctx.Stdout(), "%v\n", err) return err } fmt.Fprintf(ctx.Stdout(), "success\n") } } return nil } return ctx.Run().Function(installDepsFn, "Install dependencies") }