Example #1
0
// gitCookies attempts to read and parse cookies from the .gitcookies file in
// the users home directory.
func gitCookies(ctx *tool.Context) []*http.Cookie {
	cookies := []*http.Cookie{}

	homeDir := os.Getenv("HOME")
	if homeDir == "" {
		return cookies
	}

	cookieFile := filepath.Join(homeDir, ".gitcookies")
	bytes, err := ctx.Run().ReadFile(cookieFile)
	if err != nil {
		return cookies
	}

	lines := strings.Split(string(bytes), "\n")
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}
		cookie, err := parseCookie(line)
		if err != nil {
			fmt.Fprintf(ctx.Stderr(), "error parsing cookie in .gitcookies: %v\n", err)
		} else {
			cookies = append(cookies, cookie)
		}
	}
	return cookies
}
Example #2
0
// 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)
}
Example #3
0
// 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
}
Example #4
0
// InstallTools installs the tools from the given directory into
// $JIRI_ROOT/devtools/bin.
func InstallTools(ctx *tool.Context, dir string) error {
	ctx.TimerPush("install tools")
	defer ctx.TimerPop()
	if ctx.DryRun() {
		// In "dry run" mode, no binaries are built.
		return nil
	}
	binDir, err := ToAbs(devtoolsBinDir)
	if err != nil {
		return err
	}
	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		return fmt.Errorf("ReadDir(%v) failed: %v", dir, err)
	}
	failed := false
	for _, fi := range fis {
		installFn := func() error {
			src := filepath.Join(dir, fi.Name())
			dst := filepath.Join(binDir, fi.Name())
			if err := ctx.Run().Rename(src, dst); err != nil {
				return err
			}
			return nil
		}
		opts := runutil.Opts{Verbose: true}
		if err := ctx.Run().FunctionWithOpts(opts, installFn, "install tool %q", fi.Name()); err != nil {
			fmt.Fprintf(ctx.Stderr(), "%v\n", err)
			failed = true
		}
	}
	if failed {
		return cmdline.ErrExitCode(2)
	}

	// Delete old "v23" tool, and the old jiri-xprofile command.
	// TODO(nlacasse): Once everybody has had a chance to update, remove this
	// code.
	v23SubCmds := []string{
		"jiri-xprofile",
		"v23",
	}
	for _, subCmd := range v23SubCmds {
		subCmdPath := filepath.Join(binDir, subCmd)
		if err := ctx.Run().RemoveAll(subCmdPath); err != nil {
			return err
		}
	}

	return nil
}
Example #5
0
func initCommand(ctx *tool.Context, args []string) error {
	if len(args) == 0 {
		return fmt.Errorf("no profiles specified")
	}
	for _, n := range args {
		if mgr := profiles.LookupManager(n); mgr == nil {
			return fmt.Errorf("profile %v is not available, use \"list --available\" to see the list of available profiles", n)
		}
	}
	if err := profiles.Read(ctx, manifestFlag); err != nil {
		fmt.Fprintf(ctx.Stderr(), "Failed to read manifest: %v", err)
		return err
	}
	return nil
}
Example #6
0
// buildToolsFromMaster builds and installs all jiri tools using the version
// available in the local master branch of the tools repository. Notably, this
// function does not perform any version control operation on the master
// branch.
func buildToolsFromMaster(ctx *tool.Context, tools Tools, outputDir string) error {
	localProjects, err := LocalProjects(ctx, FastScan)
	if err != nil {
		return err
	}
	failed := false

	toolsToBuild, toolProjects := Tools{}, Projects{}
	toolNames := []string{} // Used for logging purposes.
	for _, tool := range tools {
		// Skip tools with no package specified. Besides increasing
		// robustness, this step also allows us to create jiri root
		// fakes without having to provide an implementation for the "jiri"
		// tool, which every manifest needs to specify.
		if tool.Package == "" {
			continue
		}
		project, ok := localProjects[tool.Project]
		if !ok {
			fmt.Errorf("unknown project %v for tool %v", tool.Project, tool.Name)
		}
		toolProjects[tool.Project] = project
		toolsToBuild[tool.Name] = tool
		toolNames = append(toolNames, tool.Name)
	}

	updateFn := func() error {
		return ApplyToLocalMaster(ctx, toolProjects, func() error {
			return BuildTools(ctx, toolsToBuild, outputDir)
		})
	}

	// Always log the output of updateFn, irrespective of
	// the value of the verbose flag.
	opts := runutil.Opts{Verbose: true}
	if err := ctx.Run().FunctionWithOpts(opts, updateFn, "build tools: %v", strings.Join(toolNames, " ")); err != nil {
		fmt.Fprintf(ctx.Stderr(), "%v\n", err)
		failed = true
	}
	if failed {
		return cmdline.ErrExitCode(2)
	}
	return nil
}
Example #7
0
// ParseNames identifies the set of projects that a jiri command should
// be applied to.
func ParseNames(ctx *tool.Context, args []string, defaultProjects map[string]struct{}) (map[string]Project, error) {
	projects, _, err := ReadManifest(ctx)
	if err != nil {
		return nil, err
	}
	result := map[string]Project{}
	if len(args) == 0 {
		// Use the default set of projects.
		args = set.String.ToSlice(defaultProjects)
	}
	for _, name := range args {
		if project, ok := projects[name]; ok {
			result[name] = project
		} else {
			// Issue a warning if the target project does not exist in the
			// project manifest.
			fmt.Fprintf(ctx.Stderr(), "WARNING: project %q does not exist in the project manifest and will be skipped\n", name)
		}
	}
	return result, nil
}
Example #8
0
// CurrentManifest returns a manifest that identifies the result of
// the most recent "jiri update" invocation.
func CurrentManifest(ctx *tool.Context) (*Manifest, error) {
	currentManifestPath, err := ToAbs(currentManifestFileName)
	if err != nil {
		return nil, err
	}
	bytes, err := ctx.Run().ReadFile(currentManifestPath)
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Fprintf(ctx.Stderr(), `WARNING: Could not find %s.
The contents of this file are stored as metadata in binaries the jiri
tool builds. To fix this problem, please run "jiri update".
`, currentManifestPath)
			return &Manifest{}, nil
		}
		return nil, err
	}
	var m Manifest
	if err := xml.Unmarshal(bytes, &m); err != nil {
		return nil, fmt.Errorf("Unmarshal(%v) failed: %v", string(bytes), err)
	}
	return &m, nil
}
Example #9
0
func updateProjects(ctx *tool.Context, remoteProjects Projects, gc bool) error {
	ctx.TimerPush("update projects")
	defer ctx.TimerPop()

	scanMode := FastScan
	if gc {
		scanMode = FullScan
	}
	localProjects, err := LocalProjects(ctx, scanMode)
	if err != nil {
		return err
	}

	gitHost, gitHostErr := GitHost(ctx)
	if gitHostErr == nil && googlesource.IsGoogleSourceHost(gitHost) {
		// Attempt to get the repo statuses from remote so we can detect when a
		// local project is already up-to-date.
		if repoStatuses, err := googlesource.GetRepoStatuses(ctx, gitHost); err != nil {
			// Log the error but don't fail.
			fmt.Fprintf(ctx.Stderr(), "Error fetching repo statuses from remote: %v\n", err)
		} else {
			for name, rp := range remoteProjects {
				status, ok := repoStatuses[rp.Name]
				if !ok {
					continue
				}
				masterRev, ok := status.Branches["master"]
				if !ok || masterRev == "" {
					continue
				}
				rp.Revision = masterRev
				remoteProjects[name] = rp
			}
		}
	}

	ops, err := computeOperations(localProjects, remoteProjects, gc)
	if err != nil {
		return err
	}

	for _, op := range ops {
		if err := op.Test(ctx); err != nil {
			return err
		}
	}
	failed := false
	manifest := &Manifest{Label: ctx.Manifest()}
	for _, op := range ops {
		updateFn := func() error { return op.Run(ctx, manifest) }
		// Always log the output of updateFn, irrespective of
		// the value of the verbose flag.
		opts := runutil.Opts{Verbose: true}
		if err := ctx.Run().FunctionWithOpts(opts, updateFn, "%v", op); err != nil {
			fmt.Fprintf(ctx.Stderr(), "%v\n", err)
			failed = true
		}
	}
	if failed {
		return cmdline.ErrExitCode(2)
	}
	if err := writeCurrentManifest(ctx, manifest); err != nil {
		return err
	}
	return nil
}