// ThirdPartyCCodePath returns that path to the directory containing built // binaries for the target OS and architecture. func ThirdPartyCCodePath(os, arch string) (string, error) { root, err := project.JiriRoot() if err != nil { return "", err } return filepath.Join(root, "third_party", "cout", fmt.Sprintf("%s_%s", os, arch)), nil }
// 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 Init(defaultManifestFilename string) { targetFlag = profiles.DefaultTarget() var err error rootDir, err = project.JiriRoot() if err != nil { panic(err) } manifest := filepath.Join(rootDir, defaultManifestFilename) // Every sub-command accepts: --manifest for _, fs := range []*flag.FlagSet{ &cmdInstall.Flags, &cmdUpdate.Flags, &cmdCleanup.Flags, &cmdUninstall.Flags, &cmdEnv.Flags, &cmdList.Flags, &cmdRecreate.Flags} { profiles.RegisterManifestFlag(fs, &manifestFlag, manifest) } // install accepts: --target and, --env. profiles.RegisterTargetAndEnvFlags(&cmdInstall.Flags, &targetFlag) // uninstall and env accept: --target, for _, fs := range []*flag.FlagSet{ &cmdUninstall.Flags, &cmdEnv.Flags} { profiles.RegisterTargetFlag(fs, &targetFlag) } // uninstall accept --all-targets but with different defaults. cmdUninstall.Flags.BoolVar(&allFlag, "all-targets", false, "apply to all targets for the specified profile(s)") // update accepts --v cmdUpdate.Flags.BoolVar(&verboseFlag, "v", false, "print more detailed information") // list accepts --show-manifest, --availabe, --v cmdList.Flags.BoolVar(&showManifestFlag, "show-manifest", false, "print out the manifest file") cmdList.Flags.BoolVar(&availableFlag, "available", false, "print the list of available profiles") cmdList.Flags.BoolVar(&verboseFlag, "v", false, "print more detailed information") // env accepts --profile cmdEnv.Flags.StringVar(&profileFlag, "profile", "", "the profile whose environment is to be displayed") for _, mgr := range profiles.Managers() { profiles.LookupManager(mgr).AddFlags(&cmdInstall.Flags, profiles.Install) profiles.LookupManager(mgr).AddFlags(&cmdUninstall.Flags, profiles.Uninstall) } }
// ThirdPartyBinPath returns the path to the given third-party tool // taking into account the host and the target Go architecture. func ThirdPartyBinPath(name string) (string, error) { root, err := project.JiriRoot() if err != nil { return "", err } bin := filepath.Join(root, "third_party", "go", "bin", name) goArch := os.Getenv("GOARCH") machineArch, err := host.Arch() if err != nil { return "", err } if goArch != "" && goArch != machineArch { bin = filepath.Join(root, "third_party", "go", "bin", fmt.Sprintf("%s_%s", runtime.GOOS, goArch), name) } return bin, nil }
// TestJiriRootSymlink checks that JiriRoot interprets the value // of the JIRI_ROOT environment variable as a path, evaluates any // symlinks the path might contain, and returns the result. func TestJiriRootSymlink(t *testing.T) { ctx := tool.NewDefaultContext() // Create a temporary directory. tmpDir, err := ctx.Run().TempDir("", "") if err != nil { t.Fatalf("TempDir() failed: %v", err) } defer ctx.Run().RemoveAll(tmpDir) // Make sure tmpDir is not a symlink itself. tmpDir, err = filepath.EvalSymlinks(tmpDir) if err != nil { t.Fatalf("EvalSymlinks(%v) failed: %v", tmpDir, err) } // Create a directory and a symlink to it. root, perm := filepath.Join(tmpDir, "root"), os.FileMode(0700) if err := ctx.Run().MkdirAll(root, perm); err != nil { t.Fatalf("%v", err) } symRoot := filepath.Join(tmpDir, "sym_root") if err := ctx.Run().Symlink(root, symRoot); err != nil { t.Fatalf("%v", err) } // Set the JIRI_ROOT to the symlink created above and check // that JiriRoot() evaluates the symlink. oldRoot := os.Getenv("JIRI_ROOT") if err := os.Setenv("JIRI_ROOT", symRoot); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) got, err := project.JiriRoot() if err != nil { t.Fatalf("%v", err) } if want := root; got != want { t.Fatalf("unexpected output: got %v, want %v", got, want) } }
func runUpdate(env *cmdline.Env, _ []string) error { ctx := tool.NewContextFromEnv(env) // Create a snapshot of the current state of all projects and // write it to the $JIRI_ROOT/.update_history folder. root, err := project.JiriRoot() if err != nil { return err } snapshotFile := filepath.Join(root, ".update_history", time.Now().Format(time.RFC3339)) if err := project.CreateSnapshot(ctx, snapshotFile); err != nil { return err } // Update all projects to their latest version. // Attempt <attemptsFlag> times before failing. updateFn := func() error { return project.UpdateUniverse(ctx, gcFlag) } return retry.Function(ctx, updateFn, retry.AttemptsOpt(attemptsFlag)) }
func TestEnvFromTarget(t *testing.T) { profiles.Clear() root, _ := project.JiriRoot() ctx := tool.NewDefaultContext() profiles.InstallProfile("a", "root") profiles.InstallProfile("b", "root") t1, t2 := &profiles.Target{}, &profiles.Target{} t1.Set("t1=cpu1-os1") t1.Env.Set("A=B C=D, B=C Z=Z") t2.Set("t1=cpu1-os1") t2.Env.Set("A=Z,B=Z,Z=Z") profiles.AddProfileTarget("a", *t1) profiles.AddProfileTarget("b", *t2) tmpdir, err := ioutil.TempDir(".", "pdb") if err != nil { t.Fatal(err) } filename := filepath.Join("release", "go", "src", "v.io", "jiri", "profiles", tmpdir, "manifest") if err := profiles.Write(ctx, filepath.Join(root, filename)); err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) ch, err := profiles.NewConfigHelper(ctx, profiles.UseProfiles, filename) if err != nil { t.Fatal(err) } ch.Vars = envvar.VarsFromSlice([]string{}) target, _ := profiles.NewTarget("t1=") ch.SetEnvFromProfiles(map[string]string{"A": " "}, map[string]bool{"Z": true}, "a,b", target) vars := ch.ToMap() if got, want := len(vars), 3; got != want { t.Errorf("got %v, want %v", got, want) } if got, want := ch.Get("A"), "B C=D Z"; got != want { t.Errorf("got %v, want %v", got, want) } if got, want := ch.Get("B"), "Z"; got != want { t.Errorf("got %v, want %v", got, want) } }
// NewConfigHelper creates a new config helper. If filename is of non-zero // length then that file will be read as a profiles manifest file, if not, the // existing, if any, in-memory profiles information will be used. If SkipProfiles // is specified for profilesMode, then no profiles are used. func NewConfigHelper(ctx *tool.Context, profilesMode ProfilesMode, filename string) (*ConfigHelper, error) { root, err := project.JiriRoot() if err != nil { return nil, err } config, err := util.LoadConfig(ctx) if err != nil { return nil, err } projects, tools, err := project.ReadManifest(ctx) if err != nil { return nil, err } if profilesMode == UseProfiles && len(filename) > 0 { if err := Read(ctx, filepath.Join(root, filename)); err != nil { return nil, err } } ch := &ConfigHelper{ ctx: ctx, root: root, config: config, projects: projects, tools: tools, profilesMode: bool(profilesMode), } ch.Vars = envvar.VarsFromOS() if profilesMode == SkipProfiles { return ch, nil } ch.legacyMode = (SchemaVersion() == Original) || (len(os.Getenv("JIRI_PROFILE")) > 0) if ch.legacyMode { vars, err := util.JiriLegacyEnvironment(ch.ctx) if err != nil { return nil, err } ch.Vars = vars } return ch, nil }
func TestConfigSerialization(t *testing.T) { ctx := tool.NewDefaultContext() root, err := project.NewFakeJiriRoot(ctx) if err != nil { t.Fatalf("%v", err) } defer func() { if err := root.Cleanup(ctx); err != nil { t.Fatalf("%v", err) } }() oldRoot, err := project.JiriRoot() if err := os.Setenv("JIRI_ROOT", root.Dir); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) config := NewConfig( APICheckProjectsOpt(apiCheckProjects), CopyrightCheckProjectsOpt(copyrightCheckProjects), GoWorkspacesOpt(goWorkspaces), JenkinsMatrixJobsOpt(jenkinsMatrixJobs), ProjectTestsOpt(projectTests), TestDependenciesOpt(testDependencies), TestGroupsOpt(testGroups), TestPartsOpt(testParts), VDLWorkspacesOpt(vdlWorkspaces), ) if err := SaveConfig(ctx, config); err != nil { t.Fatalf("%v", err) } gotConfig, err := LoadConfig(ctx) if err != nil { t.Fatalf("%v", err) } testConfigAPI(t, gotConfig) }
func TestList(t *testing.T) { ctx := tool.NewDefaultContext() // Setup a fake JIRI_ROOT. root, err := project.NewFakeJiriRoot(ctx) if err != nil { t.Fatalf("%v", err) } defer func() { if err := root.Cleanup(ctx); err != nil { t.Fatalf("%v", err) } }() oldRoot, err := project.JiriRoot() if err := os.Setenv("JIRI_ROOT", root.Dir); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) remoteSnapshotDir, err := project.RemoteSnapshotDir() if err != nil { t.Fatalf("%v", err) } localSnapshotDir, err := project.LocalSnapshotDir() if err != nil { t.Fatalf("%v", err) } // Create a test suite. tests := []config{ config{ remote: false, dir: localSnapshotDir, }, config{ remote: true, dir: remoteSnapshotDir, }, } labels := []label{ label{ name: "beta", snapshots: []string{"beta-1", "beta-2", "beta-3"}, }, label{ name: "stable", snapshots: []string{"stable-1", "stable-2", "stable-3"}, }, } for _, test := range tests { remoteFlag = test.remote // Create the snapshots directory and populate it with the // data specified by the test suite. for _, label := range labels { createLabelDir(t, ctx, test.dir, label.name, label.snapshots) } // Check that running "jiri snapshot list" with no arguments // returns the expected output. var stdout bytes.Buffer env := &cmdline.Env{Stdout: &stdout} if err != nil { t.Fatalf("%v", err) } if err := runSnapshotList(env, nil); err != nil { t.Fatalf("%v", err) } got, want := stdout.String(), generateOutput(labels) if got != want { t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) } // Check that running "jiri snapshot list" with one argument // returns the expected output. stdout.Reset() if err := runSnapshotList(env, []string{"stable"}); err != nil { t.Fatalf("%v", err) } got, want = stdout.String(), generateOutput(labels[1:]) if got != want { t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) } // Check that running "jiri snapshot list" with // multiple arguments returns the expected output. stdout.Reset() if err := runSnapshotList(env, []string{"beta", "stable"}); err != nil { t.Fatalf("%v", err) } got, want = stdout.String(), generateOutput(labels) if got != want { t.Fatalf("unexpected output:\ngot\n%v\nwant\n%v\n", got, want) } } }
func TestCreate(t *testing.T) { ctx := tool.NewDefaultContext() // Setup a fake JIRI_ROOT instance. root, err := project.NewFakeJiriRoot(ctx) if err != nil { t.Fatalf("%v", err) } defer func() { if err := root.Cleanup(ctx); err != nil { t.Fatalf("%v", err) } }() // Setup the initial remote and local projects. numProjects, remoteProjects := 2, []string{} for i := 0; i < numProjects; i++ { if err := root.CreateRemoteProject(ctx, remoteProjectName(i)); err != nil { t.Fatalf("%v", err) } if err := root.AddProject(ctx, project.Project{ Name: remoteProjectName(i), Path: localProjectName(i), Remote: root.Projects[remoteProjectName(i)], }); err != nil { t.Fatalf("%v", err) } } // Point the JIRI_ROOT environment variable to the fake. oldRoot, err := project.JiriRoot() if err := os.Setenv("JIRI_ROOT", root.Dir); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) // Create initial commits in the remote projects and use // UpdateUniverse() to mirror them locally. for i := 0; i < numProjects; i++ { writeReadme(t, ctx, root.Projects[remoteProjectName(i)], "revision 1") } if err := project.UpdateUniverse(ctx, true); err != nil { t.Fatalf("%v", err) } // Create a local snapshot. var stdout bytes.Buffer env := &cmdline.Env{Stdout: &stdout} remoteFlag = false if err := runSnapshotCreate(env, []string{"test-local"}); err != nil { t.Fatalf("%v", err) } // Remove the local project repositories. for i, _ := range remoteProjects { localProject := filepath.Join(root.Dir, localProjectName(i)) if err := ctx.Run().RemoveAll(localProject); err != nil { t.Fatalf("%v", err) } } // Check that invoking the UpdateUniverse() with the local // snapshot restores the local repositories. snapshotDir, err := project.LocalSnapshotDir() if err != nil { t.Fatalf("%v", err) } snapshotFile := filepath.Join(snapshotDir, "test-local") localCtx := ctx.Clone(tool.ContextOpts{ Manifest: &snapshotFile, }) if err := project.UpdateUniverse(localCtx, true); err != nil { t.Fatalf("%v", err) } for i, _ := range remoteProjects { localProject := filepath.Join(root.Dir, localProjectName(i)) checkReadme(t, ctx, localProject, "revision 1") } // Create a remote snapshot. remoteFlag = true root.EnableRemoteManifestPush(ctx) if err := runSnapshotCreate(env, []string{"test-remote"}); err != nil { t.Fatalf("%v", err) } // Remove the local project repositories. for i, _ := range remoteProjects { localProject := filepath.Join(root.Dir, localProjectName(i)) if err := ctx.Run().RemoveAll(localProject); err != nil { t.Fatalf("%v", err) } } // Check that invoking the UpdateUniverse() with the remote snapshot // restores the local repositories. manifest := "snapshot/test-remote" remoteCtx := ctx.Clone(tool.ContextOpts{ Manifest: &manifest, }) if err := project.UpdateUniverse(remoteCtx, true); err != nil { t.Fatalf("%v", err) } for i, _ := range remoteProjects { localProject := filepath.Join(root.Dir, localProjectName(i)) checkReadme(t, ctx, localProject, "revision 1") } }
func TestOncall(t *testing.T) { ctx := tool.NewDefaultContext() root, err := project.NewFakeJiriRoot(ctx) if err != nil { t.Fatalf("%v", err) } defer func() { if err := root.Cleanup(ctx); err != nil { t.Fatalf("%v", err) } }() oldRoot, err := project.JiriRoot() if err != nil { t.Fatalf("%v", err) } if err := os.Setenv("JIRI_ROOT", root.Dir); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) // Create a oncall.v1.xml file. createOncallFile(t, ctx) type testCase struct { targetTime time.Time expectedShift *OncallShift } testCases := []testCase{ testCase{ targetTime: time.Date(2013, time.November, 5, 12, 0, 0, 0, time.Local), expectedShift: nil, }, testCase{ targetTime: time.Date(2014, time.November, 5, 12, 0, 0, 0, time.Local), expectedShift: &OncallShift{ Primary: "spetrovic", Secondary: "suharshs", Date: "Nov 5, 2014 12:00:00 PM", }, }, testCase{ targetTime: time.Date(2014, time.November, 5, 14, 0, 0, 0, time.Local), expectedShift: &OncallShift{ Primary: "spetrovic", Secondary: "suharshs", Date: "Nov 5, 2014 12:00:00 PM", }, }, testCase{ targetTime: time.Date(2014, time.November, 20, 14, 0, 0, 0, time.Local), expectedShift: &OncallShift{ Primary: "jsimsa", Secondary: "toddw", Date: "Nov 19, 2014 12:00:00 PM", }, }, } for _, test := range testCases { got, err := Oncall(ctx, test.targetTime) if err != nil { t.Fatalf("want no errors, got: %v", err) } if !reflect.DeepEqual(test.expectedShift, got) { t.Fatalf("want %#v, got %#v", test.expectedShift, got) } } }
func testSetPathHelper(t *testing.T, name string) { profiles.Clear() ctx := tool.NewDefaultContext() // Setup a fake JIRI_ROOT. root, err := project.NewFakeJiriRoot(ctx) if err != nil { t.Fatalf("%v", err) } defer func() { if err := root.Cleanup(ctx); err != nil { t.Fatalf("%v", err) } }() // Create a test project and identify it as a Go workspace. if err := root.CreateRemoteProject(ctx, "test"); err != nil { t.Fatalf("%v", err) } if err := root.AddProject(ctx, project.Project{ Name: "test", Path: "test", Remote: root.Projects["test"], }); err != nil { t.Fatalf("%v", err) } if err := root.UpdateUniverse(ctx, false); err != nil { t.Fatalf("%v", err) } var config *util.Config switch name { case "GOPATH": config = util.NewConfig(util.GoWorkspacesOpt([]string{"test", "does/not/exist"})) case "VDLPATH": config = util.NewConfig(util.VDLWorkspacesOpt([]string{"test", "does/not/exist"})) } oldRoot, err := project.JiriRoot() if err := os.Setenv("JIRI_ROOT", root.Dir); err != nil { t.Fatalf("%v", err) } defer os.Setenv("JIRI_ROOT", oldRoot) if err := profiles.Write(ctx, filepath.Join(root.Dir, "profiles-manifest")); err != nil { t.Fatal(err) } if err := util.SaveConfig(ctx, config); err != nil { t.Fatalf("%v", err) } // Retrieve Jiri_ROOT through JiriRoot() to account for symlinks. jiriRoot, err := project.JiriRoot() if err != nil { t.Fatalf("%v", err) } ch, err := profiles.NewConfigHelper(ctx, profiles.UseProfiles, "profiles-manifest") if err != nil { t.Fatal(err) } ch.Vars = envvar.VarsFromOS() ch.Set(name, "") var want string switch name { case "GOPATH": want = filepath.Join(jiriRoot, "test") ch.SetGoPath() case "VDLPATH": // Make a fake src directory. want = filepath.Join(jiriRoot, "test", "src") if err := ctx.Run().MkdirAll(want, 0755); err != nil { t.Fatalf("%v", err) } ch.SetVDLPath() } if got := ch.Get(name); got != want { t.Fatalf("unexpected value: got %v, want %v", got, want) } }