Пример #1
0
func runUpdate(jirix *jiri.X, _ []string) error {
	seq := jirix.NewSeq()
	// Create the $JIRI_ROOT/.jiri_root directory if it doesn't already exist.
	//
	// TODO(toddw): Remove this logic after the transition to .jiri_root is done.
	// The bootstrapping logic should create this directory, and jiri should fail
	// if the directory doesn't exist.
	if err := seq.MkdirAll(jirix.RootMetaDir(), 0755).Done(); err != nil {
		return err
	}

	// Update all projects to their latest version.
	// Attempt <attemptsFlag> times before failing.
	updateFn := func() error { return project.UpdateUniverse(jirix, gcFlag) }
	if err := retry.Function(jirix.Context, updateFn, retry.AttemptsOpt(attemptsFlag)); err != nil {
		return err
	}
	if err := project.WriteUpdateHistorySnapshot(jirix, ""); err != nil {
		return err
	}

	// Only attempt the bin dir transition after the update has succeeded, to
	// avoid messy partial states.
	return project.TransitionBinDir(jirix)
}
Пример #2
0
// UpdateUniverse synchronizes the content of the Vanadium fake based
// on the content of the remote manifest.
func (fake FakeJiriRoot) UpdateUniverse(gc bool) error {
	oldRoot := os.Getenv(jiri.RootEnv)
	if err := os.Setenv(jiri.RootEnv, fake.X.Root); err != nil {
		return fmt.Errorf("Setenv() failed: %v", err)
	}
	defer os.Setenv(jiri.RootEnv, oldRoot)
	if err := project.UpdateUniverse(fake.X, gc); err != nil {
		return err
	}
	return nil
}
Пример #3
0
func TestRemoteImportCycle(t *testing.T) {
	fake, cleanup := jiritest.NewFakeJiriRoot(t)
	defer cleanup()

	// Set up two remote manifest projects, remote1 and remote1.
	if err := fake.CreateRemoteProject("remote1"); err != nil {
		t.Fatal(err)
	}
	if err := fake.CreateRemoteProject("remote2"); err != nil {
		t.Fatal(err)
	}
	remote1 := fake.Projects["remote1"]
	remote2 := fake.Projects["remote2"]

	fileA, fileB := filepath.Join(remote1, "A"), filepath.Join(remote2, "B")

	// Set up the cycle .jiri_manifest -> remote1+A -> remote2+B -> remote1+A
	jiriManifest := project.Manifest{
		Imports: []project.Import{
			{Manifest: "A", Name: "n1", Remote: remote1},
		},
	}
	manifestA := project.Manifest{
		Imports: []project.Import{
			{Manifest: "B", Name: "n2", Remote: remote2},
		},
	}
	manifestB := project.Manifest{
		Imports: []project.Import{
			{Manifest: "A", Name: "n3", Remote: remote1},
		},
	}
	if err := jiriManifest.ToFile(fake.X, fake.X.JiriManifestFile()); err != nil {
		t.Fatal(err)
	}
	if err := manifestA.ToFile(fake.X, fileA); err != nil {
		t.Fatal(err)
	}
	if err := manifestB.ToFile(fake.X, fileB); err != nil {
		t.Fatal(err)
	}
	commitFile(t, fake.X, remote1, fileA, "commit A")
	commitFile(t, fake.X, remote2, fileB, "commit B")

	// The update should complain about the cycle.
	err := project.UpdateUniverse(fake.X, false)
	if got, want := fmt.Sprint(err), "import cycle detected in remote manifest imports"; !strings.Contains(got, want) {
		t.Errorf("got error %v, want substr %v", got, want)
	}
}
Пример #4
0
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))
}
Пример #5
0
func TestFileImportCycle(t *testing.T) {
	jirix, cleanup := jiritest.NewX(t)
	defer cleanup()

	// Set up the cycle .jiri_manifest -> A -> B -> A
	jiriManifest := project.Manifest{
		LocalImports: []project.LocalImport{
			{File: "A"},
		},
	}
	manifestA := project.Manifest{
		LocalImports: []project.LocalImport{
			{File: "B"},
		},
	}
	manifestB := project.Manifest{
		LocalImports: []project.LocalImport{
			{File: "A"},
		},
	}
	if err := jiriManifest.ToFile(jirix, jirix.JiriManifestFile()); err != nil {
		t.Fatal(err)
	}
	if err := manifestA.ToFile(jirix, filepath.Join(jirix.Root, "A")); err != nil {
		t.Fatal(err)
	}
	if err := manifestB.ToFile(jirix, filepath.Join(jirix.Root, "B")); err != nil {
		t.Fatal(err)
	}

	// The update should complain about the cycle.
	err := project.UpdateUniverse(jirix, false)
	if got, want := fmt.Sprint(err), "import cycle detected in local manifest files"; !strings.Contains(got, want) {
		t.Errorf("got error %v, want substr %v", got, want)
	}
}
Пример #6
0
// TestCreate tests creating and checking out a snapshot.
func TestCreate(t *testing.T) {
	resetFlags()
	defer resetFlags()
	fake, cleanup := jiritest.NewFakeJiriRoot(t)
	defer cleanup()
	s := fake.X.NewSeq()

	// Setup the initial remote and local projects.
	numProjects, remoteProjects := 2, []string{}
	for i := 0; i < numProjects; i++ {
		if err := fake.CreateRemoteProject(remoteProjectName(i)); err != nil {
			t.Fatalf("%v", err)
		}
		if err := fake.AddProject(project.Project{
			Name:   remoteProjectName(i),
			Path:   localProjectName(i),
			Remote: fake.Projects[remoteProjectName(i)],
		}); err != nil {
			t.Fatalf("%v", err)
		}
	}

	// Create initial commits in the remote projects and use UpdateUniverse()
	// to mirror them locally.
	for i := 0; i < numProjects; i++ {
		writeReadme(t, fake.X, fake.Projects[remoteProjectName(i)], "revision 1")
	}
	if err := project.UpdateUniverse(fake.X, true); err != nil {
		t.Fatalf("%v", err)
	}

	// Create a snapshot.
	var stdout bytes.Buffer
	fake.X.Context = tool.NewContext(tool.ContextOpts{Stdout: &stdout})
	if err := runSnapshotCreate(fake.X, []string{"test-local"}); err != nil {
		t.Fatalf("%v", err)
	}

	// Remove the local project repositories.
	for i, _ := range remoteProjects {
		localProject := filepath.Join(fake.X.Root, localProjectName(i))
		if err := s.RemoveAll(localProject).Done(); err != nil {
			t.Fatalf("%v", err)
		}
	}

	// Check that invoking the UpdateUniverse() with the snapshot restores the
	// local repositories.
	snapshotDir := filepath.Join(fake.X.Root, defaultSnapshotDir)
	snapshotFile := filepath.Join(snapshotDir, "test-local")
	localX := fake.X.Clone(tool.ContextOpts{
		Manifest: &snapshotFile,
	})
	if err := project.UpdateUniverse(localX, true); err != nil {
		t.Fatalf("%v", err)
	}
	for i, _ := range remoteProjects {
		localProject := filepath.Join(fake.X.Root, localProjectName(i))
		checkReadme(t, fake.X, localProject, "revision 1")
	}
}
Пример #7
0
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")
	}
}