Beispiel #1
0
// MissingOSPackages returns the subset of the supplied packages that are
// missing from the underlying operating system and hence will need to
// be installed.
func MissingOSPackages(jirix *jiri.X, pkgs []string) ([]string, error) {
	installedPkgs := map[string]bool{}
	switch runtime.GOOS {
	case "linux":
		if IsFNLHost() {
			fmt.Fprintf(jirix.Stdout(), "skipping %v on FNL host\n", pkgs)
			break
		}
		var err error
		installedPkgs, err = linuxList(jirix, pkgs)
		if err != nil {
			return nil, err
		}
	case "darwin":
		var err error
		installedPkgs, err = brewList(jirix)
		if err != nil {
			return nil, err
		}
	}
	missing := []string{}
	for _, pkg := range pkgs {
		if !installedPkgs[pkg] {
			missing = append(missing, pkg)
		}
	}
	return missing, nil
}
Beispiel #2
0
func packagesImpl(jirix *jiri.X, cl *packagesFlagValues, args []string) error {
	mgrs, _, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	cl.target.UseCommandLineEnv()
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	s := jirix.NewSeq()
	installPackages := cl.installPackages
	// Never ask a subcommand to install packages.
	cl.installPackages = false
	for _, mgr := range mgrs {
		cmds, err := mgr.packageCmds(jirix, cl, root)
		if err != nil {
			return err
		}
		for _, cmd := range cmds {
			if installPackages {
				if err := s.Verbose(true).Last(cmd[0], cmd[1:]...); err != nil {
					return err
				}
			} else {
				fmt.Fprintf(jirix.Stdout(), "%s\n", strings.TrimSpace(strings.Join(cmd, " ")))
			}
		}
	}
	return nil
}
Beispiel #3
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)
}
Beispiel #4
0
func linuxList(jirix *jiri.X, pkgs []string) (map[string]bool, error) {
	aptitude, yum, pacman := UsingAptitude(jirix), UsingYum(jirix), UsingPacman(jirix)
	cmd := ""
	opt := ""
	switch {
	case aptitude:
		cmd = "dpkg"
		opt = "-L"
	case yum:
		cmd = "yum"
		opt = "list"
	case pacman:
		cmd = "pacman"
		opt = "-Q"
	default:
		return nil, fmt.Errorf("no usable package manager found, tested for aptitude, yum and pacman")
	}
	s := jirix.NewSeq()
	installedPkgs := map[string]bool{}
	for _, pkg := range pkgs {
		if err := s.Capture(ioutil.Discard, ioutil.Discard).Last(cmd, opt, pkg); err == nil {
			installedPkgs[pkg] = true
		}
	}
	return installedPkgs, nil
}
Beispiel #5
0
func (ip *inproc) uninstall(jirix *jiri.X, cl *uninstallFlagValues, root jiri.RelPath) error {
	profile := ip.db.LookupProfile(ip.installer, ip.name)
	if profile == nil {
		fmt.Fprintf(jirix.Stdout(), "%s is not installed\n", ip.qname)
		return nil
	}
	mgr := profilesmanager.LookupManager(ip.qname)
	var targets []*profiles.Target
	if cl.allTargets {
		targets = profile.Targets()
	} else {
		def, err := targetAtDefaultVersion(mgr, cl.target)
		if err != nil {
			return err
		}
		targets = []*profiles.Target{&def}
	}
	for _, target := range targets {
		if err := mgr.Uninstall(jirix, ip.db, root, *target); err != nil {
			logResult(jirix, "Uninstall", mgr, *target, err)
			return err
		}
		logResult(jirix, "Uninstall", mgr, *target, nil)
	}
	return nil
}
Beispiel #6
0
func runRebuild(jirix *jiri.X, args []string) (e error) {
	projects, tools, err := project.LoadManifest(jirix)
	if err != nil {
		return err
	}

	// Create a temporary directory in which tools will be built.
	tmpDir, err := jirix.NewSeq().TempDir("", "tmp-jiri-rebuild")
	if err != nil {
		return fmt.Errorf("TempDir() failed: %v", err)
	}

	// Make sure we cleanup the temp directory.
	defer collect.Error(func() error { return jirix.NewSeq().RemoveAll(tmpDir).Done() }, &e)

	// Paranoid sanity checking.
	if _, ok := tools[project.JiriName]; !ok {
		return fmt.Errorf("tool %q not found", project.JiriName)
	}

	// Build and install tools.
	if err := project.BuildTools(jirix, projects, tools, tmpDir); err != nil {
		return err
	}
	return project.InstallTools(jirix, tmpDir)
}
Beispiel #7
0
func (ip *inproc) update(jirix *jiri.X, cl *updateFlagValues, root jiri.RelPath) error {
	profile := ip.db.LookupProfile(ip.installer, ip.name)
	if profile == nil {
		// silently ignore uninstalled profile.
		return nil
	}
	mgr := profilesmanager.LookupManager(ip.qname)
	vi := mgr.VersionInfo()
	for _, target := range profile.Targets() {
		if vi.IsTargetOlderThanDefault(target.Version()) {
			// Check if default target is already installed.
			defTarget := *target
			defTarget.SetVersion(vi.Default())
			if profiles.FindTarget(profile.Targets(), &defTarget) != nil {
				// Default target is already installed.  Skip.
				continue
			}
			if cl.verbose {
				fmt.Fprintf(jirix.Stdout(), "Updating %s %s from %q to %s\n", ip.qname, target, target.Version(), vi)
			}
			err := mgr.Install(jirix, ip.db, root, defTarget)
			logResult(jirix, "Update", mgr, defTarget, err)
			if err != nil {
				return err
			}
		} else {
			if cl.verbose {
				fmt.Fprintf(jirix.Stdout(), "%s %s at %q is up to date(%s)\n", ip.qname, target, target.Version(), vi)
			}
		}
	}
	return nil
}
Beispiel #8
0
func getCommitMessageFileName(jirix *jiri.X, branch string) (string, error) {
	topLevel, err := gitutil.New(jirix.NewSeq()).TopLevel()
	if err != nil {
		return "", err
	}
	return filepath.Join(topLevel, jiri.ProjectMetaDir, branch, commitMessageFileName), nil
}
Beispiel #9
0
// checkDependents makes sure that all CLs in the sequence of
// dependent CLs leading to (but not including) the current branch
// have been exported to Gerrit.
func checkDependents(jirix *jiri.X) (e error) {
	originalBranch, err := gitutil.New(jirix.NewSeq()).CurrentBranchName()
	if err != nil {
		return err
	}
	branches, err := getDependentCLs(jirix, originalBranch)
	if err != nil {
		return err
	}
	for i := 1; i < len(branches); i++ {
		file, err := getCommitMessageFileName(jirix, branches[i])
		if err != nil {
			return err
		}
		if _, err := jirix.NewSeq().Stat(file); err != nil {
			if !runutil.IsNotExist(err) {
				return err
			}
			return fmt.Errorf(`Failed to export the branch %q to Gerrit because its ancestor %q has not been exported to Gerrit yet.
The following steps are needed before the operation can be retried:
$ git checkout %v
$ jiri cl mail
$ git checkout %v
# retry the original command
`, originalBranch, branches[i], branches[i], originalBranch)
		}
	}

	return nil
}
Beispiel #10
0
func findProfileSubcommands(jirix *jiri.X) []string {
	if !runSubcommands {
		return nil
	}
	cmds, _ := lookpath.LookPrefix(jirix.Env(), "jiri-profile-", nil)
	return cmds
}
Beispiel #11
0
func installImpl(jirix *jiri.X, cl *installFlagValues, args []string) error {
	mgrs, db, err := availableProfileManagers(jirix, cl.dbPath, args)
	if err != nil {
		return err
	}
	cl.target.UseCommandLineEnv()
	newMgrs := []profileManager{}
	for _, mgr := range mgrs {
		name := mgr.mgrName()
		if !cl.force {
			installer, profile := profiles.SplitProfileName(name)
			if p := db.LookupProfileTarget(installer, profile, cl.target); p != nil {
				fmt.Fprintf(jirix.Stdout(), "%v %v is already installed as %v\n", name, cl.target, p)
				continue
			}
		}
		newMgrs = append(newMgrs, mgr)
	}
	root := jiri.NewRelPath(cl.root).Join(profileInstaller)
	for _, mgr := range newMgrs {
		if err := mgr.install(jirix, cl, root); err != nil {
			return err
		}
	}
	return writeDB(jirix, db, profileInstaller, cl.dbPath)
}
Beispiel #12
0
// assertFilesNotCommitted asserts that the files exist and are *not*
// committed in the current branch.
func assertFilesNotCommitted(t *testing.T, jirix *jiri.X, files []string) {
	assertFilesExist(t, jirix, files)
	for _, file := range files {
		if gitutil.New(jirix.NewSeq()).IsFileCommitted(file) {
			t.Fatalf("expected file %v not to be committed but it is", file)
		}
	}
}
Beispiel #13
0
func newmapInput(jirix *jiri.X, state *project.ProjectState, key project.ProjectKey, index, total int) *mapInput {
	return &mapInput{
		ProjectState: state,
		key:          key,
		jirix:        jirix.Clone(tool.ContextOpts{}),
		index:        index,
		total:        total,
	}
}
Beispiel #14
0
// Untar untars the file in srcFile and puts resulting files in directory dstDir.
func Untar(jirix *jiri.X, srcFile, dstDir string) error {
	s := jirix.NewSeq()
	if err := s.MkdirAll(dstDir, 0755).Done(); err != nil {
		return err
	}
	return s.Output([]string{"untarring " + srcFile + " into " + dstDir}).
		Pushd(dstDir).
		Last("tar", "xvf", srcFile)
}
Beispiel #15
0
// assertFileContent asserts that the content of the given file
// matches the expected content.
func assertFileContent(t *testing.T, jirix *jiri.X, file, want string) {
	got, err := jirix.NewSeq().ReadFile(file)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	if string(got) != want {
		t.Fatalf("unexpected content of file %v: got %v, want %v", file, got, want)
	}
}
Beispiel #16
0
// assertFilesPushedToRef asserts that the given files have been
// pushed to the given remote repository reference.
func assertFilesPushedToRef(t *testing.T, jirix *jiri.X, repoPath, gerritPath, pushedRef string, files []string) {
	chdir(t, jirix, gerritPath)
	assertCommitCount(t, jirix, pushedRef, "master", 1)
	if err := gitutil.New(jirix.NewSeq()).CheckoutBranch(pushedRef); err != nil {
		t.Fatalf("%v", err)
	}
	assertFilesCommitted(t, jirix, files)
	chdir(t, jirix, repoPath)
}
Beispiel #17
0
// assertStashSize asserts that the stash size matches the expected
// size.
func assertStashSize(t *testing.T, jirix *jiri.X, want int) {
	got, err := gitutil.New(jirix.NewSeq()).StashSize()
	if err != nil {
		t.Fatalf("%v", err)
	}
	if got != want {
		t.Fatalf("unxpected stash size: got %v, want %v", got, want)
	}
}
Beispiel #18
0
// assertCommitCount asserts that the commit count between two
// branches matches the expectedCount.
func assertCommitCount(t *testing.T, jirix *jiri.X, branch, baseBranch string, expectedCount int) {
	got, err := gitutil.New(jirix.NewSeq()).CountCommits(branch, baseBranch)
	if err != nil {
		t.Fatalf("%v", err)
	}
	if want := 1; got != want {
		t.Fatalf("unexpected number of commits: got %v, want %v", got, want)
	}
}
Beispiel #19
0
// assertFilesDoNotExist asserts that the files do not exist.
func assertFilesDoNotExist(t *testing.T, jirix *jiri.X, files []string) {
	s := jirix.NewSeq()
	for _, file := range files {
		if _, err := s.Stat(file); err != nil && !runutil.IsNotExist(err) {
			t.Fatalf("%v", err)
		} else if err == nil {
			t.Fatalf("expected file %v to not exist but it did", file)
		}
	}
}
Beispiel #20
0
// commitFile commits a file with the specified content into a branch
func commitFile(t *testing.T, jirix *jiri.X, filename string, content string) {
	s := jirix.NewSeq()
	if err := s.WriteFile(filename, []byte(content), 0644).Done(); err != nil {
		t.Fatalf("%v", err)
	}
	commitMessage := "Commit " + filename
	if err := gitutil.New(jirix.NewSeq()).CommitFile(filename, commitMessage); err != nil {
		t.Fatalf("%v", err)
	}
}
Beispiel #21
0
// createRepoFromOrigin creates a Git repo tracking origin/master.
func createRepoFromOrigin(t *testing.T, jirix *jiri.X, subpath string, originPath string) string {
	repoPath := createRepo(t, jirix, subpath)
	chdir(t, jirix, repoPath)
	if err := gitutil.New(jirix.NewSeq()).AddRemote("origin", originPath); err != nil {
		t.Fatalf("%v", err)
	}
	if err := gitutil.New(jirix.NewSeq()).Pull("origin", "master"); err != nil {
		t.Fatalf("%v", err)
	}
	return repoPath
}
Beispiel #22
0
// submit mocks a Gerrit review submit by pushing the Gerrit remote to origin.
// Actually origin pulls from Gerrit since origin isn't actually a bare git repo.
// Some of our tests actually rely on accessing .git in origin, so it must be non-bare.
func submit(t *testing.T, jirix *jiri.X, originPath string, gerritPath string, review *review) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("Getwd() failed: %v", err)
	}
	chdir(t, jirix, originPath)
	expectedRef := gerrit.Reference(review.CLOpts)
	if err := gitutil.New(jirix.NewSeq()).Pull(gerritPath, expectedRef); err != nil {
		t.Fatalf("Pull gerrit to origin failed: %v", err)
	}
	chdir(t, jirix, cwd)
}
Beispiel #23
0
func brewList(jirix *jiri.X) (map[string]bool, error) {
	var out bytes.Buffer
	err := jirix.NewSeq().Capture(&out, &out).Last("brew", "list")
	if err != nil || tool.VerboseFlag {
		fmt.Fprintf(jirix.Stdout(), "%s", out.String())
	}
	scanner := bufio.NewScanner(&out)
	pkgs := map[string]bool{}
	for scanner.Scan() {
		pkgs[scanner.Text()] = true
	}
	return pkgs, err
}
Beispiel #24
0
func checkReadme(t *testing.T, jirix *jiri.X, p project.Project, message string) {
	if _, err := jirix.NewSeq().Stat(p.Path); err != nil {
		t.Fatalf("%v", err)
	}
	readmeFile := filepath.Join(p.Path, "README")
	data, err := ioutil.ReadFile(readmeFile)
	if err != nil {
		t.Fatalf("ReadFile(%v) failed: %v", readmeFile, err)
	}
	if got, want := data, []byte(message); bytes.Compare(got, want) != 0 {
		t.Fatalf("unexpected content in project %v:\ngot\n%s\nwant\n%s\n", p.Name, got, want)
	}
}
Beispiel #25
0
// Checks that /.jiri/ is ignored in a local project checkout
func checkMetadataIsIgnored(t *testing.T, jirix *jiri.X, p project.Project) {
	if _, err := jirix.NewSeq().Stat(p.Path); err != nil {
		t.Fatalf("%v", err)
	}
	gitInfoExcludeFile := filepath.Join(p.Path, ".git", "info", "exclude")
	data, err := ioutil.ReadFile(gitInfoExcludeFile)
	if err != nil {
		t.Fatalf("ReadFile(%v) failed: %v", gitInfoExcludeFile, err)
	}
	excludeString := "/.jiri/"
	if !strings.Contains(string(data), excludeString) {
		t.Fatalf("Did not find \"%v\" in exclude file", excludeString)
	}
}
Beispiel #26
0
func newCL(jirix *jiri.X, args []string) error {
	git := gitutil.New(jirix.NewSeq())
	topLevel, err := git.TopLevel()
	if err != nil {
		return err
	}
	originalBranch, err := git.CurrentBranchName()
	if err != nil {
		return err
	}

	// Create a new branch using the current branch.
	newBranch := args[0]
	if err := git.CreateAndCheckoutBranch(newBranch); err != nil {
		return err
	}

	// Register a cleanup handler in case of subsequent errors.
	cleanup := true
	defer func() {
		if cleanup {
			git.CheckoutBranch(originalBranch, gitutil.ForceOpt(true))
			git.DeleteBranch(newBranch, gitutil.ForceOpt(true))
		}
	}()

	s := jirix.NewSeq()
	// Record the dependent CLs for the new branch. The dependent CLs
	// are recorded in a <dependencyPathFileName> file as a
	// newline-separated list of branch names.
	branches, err := getDependentCLs(jirix, originalBranch)
	if err != nil {
		return err
	}
	branches = append(branches, originalBranch)
	newMetadataDir := filepath.Join(topLevel, jiri.ProjectMetaDir, newBranch)
	if err := s.MkdirAll(newMetadataDir, os.FileMode(0755)).Done(); err != nil {
		return err
	}
	file, err := getDependencyPathFileName(jirix, newBranch)
	if err != nil {
		return err
	}
	if err := s.WriteFile(file, []byte(strings.Join(branches, "\n")), os.FileMode(0644)).Done(); err != nil {
		return err
	}

	cleanup = false
	return nil
}
Beispiel #27
0
// AtomicAction performs an action 'atomically' by keeping track of successfully
// completed actions in the supplied completion log and re-running them if they
// are not successfully logged therein after deleting the entire contents of the
// dir parameter. Consequently it does not make sense to apply AtomicAction to
// the same directory in sequence.
func AtomicAction(jirix *jiri.X, installFn func() error, dir, message string) error {
	atomicFn := func() error {
		completionLogPath := filepath.Join(dir, ".complete")
		s := jirix.NewSeq()
		if dir != "" {
			if exists, _ := s.IsDir(dir); exists {
				// If the dir exists but the completionLogPath doesn't, then it
				// means the previous action didn't finish.
				// Remove the dir so we can perform the action again.
				if exists, _ := s.IsFile(completionLogPath); !exists {
					s.RemoveAll(dir).Done()
				} else {
					if jirix.Verbose() {
						fmt.Fprintf(jirix.Stdout(), "AtomicAction: %s already completed in %s\n", message, dir)
					}
					return nil
				}
			}
		}
		if err := installFn(); err != nil {
			if dir != "" {
				s.RemoveAll(dir).Done()
			}
			return err
		}
		return s.WriteFile(completionLogPath, []byte("completed"), DefaultFilePerm).Done()
	}
	return jirix.NewSeq().Call(atomicFn, message).Done()
}
Beispiel #28
0
func checkReadme(t *testing.T, jirix *jiri.X, project, message string) {
	s := jirix.NewSeq()
	if _, err := s.Stat(project); err != nil {
		t.Fatalf("%v", err)
	}
	readmeFile := filepath.Join(project, "README")
	data, err := s.ReadFile(readmeFile)
	if err != nil {
		t.Fatalf("%v", err)
	}
	if got, want := data, []byte(message); bytes.Compare(got, want) != 0 {
		t.Fatalf("unexpected content %v:\ngot\n%s\nwant\n%s\n", project, got, want)
	}
}
Beispiel #29
0
// createTestRepos sets up three local repositories: origin, gerrit,
// and the main test repository which pulls from origin and can push
// to gerrit.
func createTestRepos(t *testing.T, jirix *jiri.X) (string, string, string) {
	// Create origin.
	originPath := createRepo(t, jirix, "origin")
	chdir(t, jirix, originPath)
	if err := gitutil.New(jirix.NewSeq()).CommitWithMessage("initial commit"); err != nil {
		t.Fatalf("%v", err)
	}
	// Create test repo.
	repoPath := createRepoFromOrigin(t, jirix, "test", originPath)
	// Add Gerrit remote.
	gerritPath := createRepoFromOrigin(t, jirix, "gerrit", originPath)
	// Switch back to test repo.
	chdir(t, jirix, repoPath)
	return repoPath, originPath, gerritPath
}
Beispiel #30
0
func (sc *subcommand) packageCmds(jirix *jiri.X, cl *packagesFlagValues, root jiri.RelPath) ([][]string, error) {
	cmd := []string{"profile-" + sc.installer, "os-packages"}
	cmd = append(cmd, cl.args()...)
	cmd = append(cmd, sc.qname)
	var out bytes.Buffer
	if err := jirix.NewSeq().Capture(&out, jirix.Stderr()).Last("jiri", cmd...); err != nil {
		return nil, err
	}
	scanner := bufio.NewScanner(&out)
	cmds := make([][]string, 0, 5)
	for scanner.Scan() {
		cmds = append(cmds, strings.Split(scanner.Text(), " "))
	}
	return cmds, nil
}