RelativePaths are always relative to JIRI_ROOT.

RelativePaths used to be more general in that they could be made
relative to anything.  The common use case was to make then relative to
JIRI_ROOT.

Now, RelativePaths must be relative to JIRI_ROOT.  When Expanding the
RelativePath to a full absolute path, a "jirix" must be passed in to
provide the value of JIRI_ROOT.

RelativePaths moved from profiles package to jiri package.

Also add jiri project to apiCheckProjects.

MultiPart: 1/2
Change-Id: Iba4483e248d8eed758486ee061e3eac2960fcbd4
diff --git a/jiri/.api b/jiri/.api
new file mode 100644
index 0000000..c76f601
--- /dev/null
+++ b/jiri/.api
@@ -0,0 +1,25 @@
+pkg jiri, const ProjectMetaDir ideal-string
+pkg jiri, const ProjectMetaFile ideal-string
+pkg jiri, const RootEnv ideal-string
+pkg jiri, const RootMetaDir ideal-string
+pkg jiri, func ExpandEnv(*X, *envvar.Vars)
+pkg jiri, func FindRoot() string
+pkg jiri, func NewRelPath(...string) RelPath
+pkg jiri, func NewX(*cmdline.Env) (*X, error)
+pkg jiri, func RunnerFunc(func(*X, []string) error) cmdline.Runner
+pkg jiri, method (*X) Clone(tool.ContextOpts) *X
+pkg jiri, method (*X) LocalManifestFile() string
+pkg jiri, method (*X) LocalSnapshotDir() string
+pkg jiri, method (*X) ManifestDir() string
+pkg jiri, method (*X) ManifestFile(string) string
+pkg jiri, method (*X) RemoteSnapshotDir() string
+pkg jiri, method (*X) ResolveManifestPath(string) (string, error)
+pkg jiri, method (*X) UsageErrorf(string, ...interface{}) error
+pkg jiri, method (RelPath) Abs(*X) string
+pkg jiri, method (RelPath) Join(...string) RelPath
+pkg jiri, method (RelPath) Symbolic() string
+pkg jiri, type RelPath string
+pkg jiri, type X struct
+pkg jiri, type X struct, Root string
+pkg jiri, type X struct, Usage func(string, ...interface{}) error
+pkg jiri, type X struct, embedded *tool.Context
diff --git a/jiri/path.go b/jiri/path.go
new file mode 100644
index 0000000..521b905
--- /dev/null
+++ b/jiri/path.go
@@ -0,0 +1,58 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jiri
+
+import (
+	"path/filepath"
+	"strings"
+
+	"v.io/x/lib/envvar"
+)
+
+// RelPath represents a relative path whose root is JIRI_ROOT.
+type RelPath string
+
+// NewRelPath returns a RelPath with path consisting of the specified
+// components.
+func NewRelPath(components ...string) RelPath {
+	return RelPath(filepath.Join(components...))
+}
+
+// Abs returns an absolute path corresponding to the RelPath rooted at the
+// JIRI_ROOT in X.
+func (rp RelPath) Abs(x *X) string {
+	return filepath.Join(x.Root, string(rp))
+}
+
+// Join returns a copy of RelPath with the specified components appended
+// to the path using filepath.Join.
+func (rp RelPath) Join(components ...string) RelPath {
+	path := append([]string{string(rp)}, components...)
+	return RelPath(filepath.Join(path...))
+}
+
+// Symbolic returns an absolute path corresponding to the RelPath, but
+// with the JIRI_ROOT environment varible at the root instead of the actual
+// value of JIRI_ROOT.
+func (rp RelPath) Symbolic() string {
+	root := "${" + RootEnv + "}"
+	if string(rp) == "" {
+		return root
+	}
+	return root + string(filepath.Separator) + string(rp)
+}
+
+// ExpandEnv expands all instances of the JIRI_ROOT variable in the supplied
+// environment with the root from jirix.
+func ExpandEnv(x *X, env *envvar.Vars) {
+	e := env.ToMap()
+	rootEnv := "${" + RootEnv + "}"
+	for k, v := range e {
+		n := strings.Replace(v, rootEnv, x.Root, -1)
+		if n != v {
+			env.Set(k, n)
+		}
+	}
+}
diff --git a/jiri/path_test.go b/jiri/path_test.go
new file mode 100644
index 0000000..1ab33f9
--- /dev/null
+++ b/jiri/path_test.go
@@ -0,0 +1,51 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package jiri
+
+import (
+	"path/filepath"
+	"testing"
+)
+
+// TestRelPath checks that RelPath methods return the correct values, and in
+// particular that Abs correctly roots the path at the given X's Root.
+func TestRelPath(t *testing.T) {
+	root1 := "/path/to/jiri-root"
+	x := &X{
+		Root: root1,
+	}
+
+	rp1 := NewRelPath("foo")
+	if got, want := string(rp1), "foo"; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+	if got, want := rp1.Abs(x), filepath.Join(root1, "foo"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+	if got, want := rp1.Symbolic(), "${"+RootEnv+"}"+string(filepath.Separator)+"foo"; got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	rp2 := rp1.Join("a", "b")
+	if got, want := string(rp2), filepath.Join("foo", "a", "b"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+	if got, want := rp2.Abs(x), filepath.Join(root1, "foo", "a", "b"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+	if got, want := rp2.Symbolic(), "${"+RootEnv+"}"+string(filepath.Separator)+filepath.Join("foo", "a", "b"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+
+	// Check Abs with different x.Root.
+	root2 := "/different/path"
+	x.Root = root2
+	if got, want := rp1.Abs(x), filepath.Join(root2, "foo"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+	if got, want := rp2.Abs(x), filepath.Join(root2, "foo", "a", "b"); got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+}
diff --git a/profiles/.api b/profiles/.api
index 3e7f821..e0f7a34 100644
--- a/profiles/.api
+++ b/profiles/.api
@@ -21,20 +21,18 @@
 pkg profiles, const V3 Version
 pkg profiles, const V4 Version
 pkg profiles, func AddProfileTarget(string, Target) error
-pkg profiles, func AtomicAction(*tool.Context, func() error, string, string) error
+pkg profiles, func AtomicAction(*jiri.X, func() error, string, string) error
 pkg profiles, func DefaultTarget() Target
-pkg profiles, func EnsureProfileTargetIsInstalled(*tool.Context, string, RelativePath, Target) error
-pkg profiles, func EnsureProfileTargetIsUninstalled(*tool.Context, string, RelativePath, Target) error
+pkg profiles, func EnsureProfileTargetIsInstalled(*jiri.X, string, jiri.RelPath, Target) error
+pkg profiles, func EnsureProfileTargetIsUninstalled(*jiri.X, string, jiri.RelPath, Target) error
 pkg profiles, func EnvFromProfile(Target, string) []string
-pkg profiles, func Fetch(*tool.Context, string, string) error
+pkg profiles, func Fetch(*jiri.X, string, string) error
 pkg profiles, func FindTarget(OrderedTargets, *Target) *Target
-pkg profiles, func FindTargetByTag(OrderedTargets, *Target) *Target
 pkg profiles, func FindTargetWithDefault(OrderedTargets, *Target) *Target
-pkg profiles, func GitCloneRepo(*tool.Context, string, string, string, os.FileMode) error
 pkg profiles, func GoEnvironmentFromOS() []string
 pkg profiles, func InitProfilesFromFlag(string, AppendJiriProfileMode) []string
 pkg profiles, func InsertTarget(OrderedTargets, *Target) OrderedTargets
-pkg profiles, func InstallPackages(*tool.Context, []string) error
+pkg profiles, func InstallPackages(*jiri.X, []string) error
 pkg profiles, func InstallProfile(string, string)
 pkg profiles, func JiriMergePolicies() MergePolicies
 pkg profiles, func LookupManager(string) Manager
@@ -43,14 +41,13 @@
 pkg profiles, func Managers() []string
 pkg profiles, func MergeEnv(map[string]MergePolicy, *envvar.Vars, ...[]string)
 pkg profiles, func NativeTarget() Target
-pkg profiles, func NewConfigHelper(*tool.Context, ProfilesMode, string) (*ConfigHelper, error)
-pkg profiles, func NewRelativePath(string, string) RelativePath
+pkg profiles, func NewConfigHelper(*jiri.X, ProfilesMode, string) (*ConfigHelper, error)
 pkg profiles, func NewTarget(string) (Target, error)
 pkg profiles, func NewTargetWithEnv(string, string) (Target, error)
 pkg profiles, func NewVersionInfo(string, map[string]interface{}, string) *VersionInfo
 pkg profiles, func ProfileMergePolicies() MergePolicies
 pkg profiles, func Profiles() []string
-pkg profiles, func Read(*tool.Context, string) error
+pkg profiles, func Read(*jiri.X, string) error
 pkg profiles, func Register(string, Manager)
 pkg profiles, func RegisterManifestFlag(*flag.FlagSet, *string, string)
 pkg profiles, func RegisterMergePoliciesFlag(*flag.FlagSet, *MergePolicies)
@@ -60,17 +57,15 @@
 pkg profiles, func RegisterTargetFlag(*flag.FlagSet, *Target)
 pkg profiles, func RemoveProfileTarget(string, Target) bool
 pkg profiles, func RemoveTarget(OrderedTargets, *Target) OrderedTargets
-pkg profiles, func RunCommand(*tool.Context, map[string]string, string, ...string) error
 pkg profiles, func SchemaVersion() Version
 pkg profiles, func UnsetGoEnvMap(map[string]string)
 pkg profiles, func UnsetGoEnvVars(*envvar.Vars)
-pkg profiles, func Unzip(*tool.Context, string, string) error
+pkg profiles, func Unzip(*jiri.X, string, string) error
 pkg profiles, func UpdateProfileTarget(string, Target) error
 pkg profiles, func WithDefaultVersion(Target) Target
-pkg profiles, func Write(*tool.Context, string) error
+pkg profiles, func Write(*jiri.X, string) error
 pkg profiles, method (*ConfigHelper) GoPath() string
 pkg profiles, method (*ConfigHelper) JiriProfile() []string
-pkg profiles, method (*ConfigHelper) LegacyProfiles() bool
 pkg profiles, method (*ConfigHelper) MergeEnv(map[string]MergePolicy, ...[]string)
 pkg profiles, method (*ConfigHelper) MergeEnvFromProfiles(map[string]MergePolicy, Target, ...string)
 pkg profiles, method (*ConfigHelper) PrependToPATH(string)
@@ -88,20 +83,18 @@
 pkg profiles, method (*ProfilesMode) IsBoolFlag() bool
 pkg profiles, method (*ProfilesMode) Set(string) error
 pkg profiles, method (*ProfilesMode) String() string
-pkg profiles, method (*RelativePath) String() string
 pkg profiles, method (*Target) Arch() string
 pkg profiles, method (*Target) Less(*Target) bool
 pkg profiles, method (*Target) OS() string
 pkg profiles, method (*Target) Set(string) error
 pkg profiles, method (*Target) SetVersion(string)
-pkg profiles, method (*Target) Tag() string
 pkg profiles, method (*Target) TargetSpecificDirname() string
 pkg profiles, method (*Target) Usage() string
 pkg profiles, method (*Target) UseCommandLineEnv()
 pkg profiles, method (*Target) Version() string
 pkg profiles, method (*VersionInfo) Default() string
-pkg profiles, method (*VersionInfo) IsNewerThanDefault(string) bool
-pkg profiles, method (*VersionInfo) IsOlderThanDefault(string) bool
+pkg profiles, method (*VersionInfo) IsTargetNewerThanDefault(string) bool
+pkg profiles, method (*VersionInfo) IsTargetOlderThanDefault(string) bool
 pkg profiles, method (*VersionInfo) Lookup(string, interface{}) error
 pkg profiles, method (*VersionInfo) Select(string) (string, error)
 pkg profiles, method (*VersionInfo) String() string
@@ -115,11 +108,6 @@
 pkg profiles, method (OrderedTargets) Less(int, int) bool
 pkg profiles, method (OrderedTargets) Sort()
 pkg profiles, method (OrderedTargets) Swap(int, int)
-pkg profiles, method (RelativePath) Expand() string
-pkg profiles, method (RelativePath) ExpandEnv(*envvar.Vars)
-pkg profiles, method (RelativePath) Join(...string) RelativePath
-pkg profiles, method (RelativePath) RelativePath() string
-pkg profiles, method (RelativePath) RootJoin(...string) RelativePath
 pkg profiles, method (Target) CommandLineEnv() Environment
 pkg profiles, method (Target) CrossCompiling() bool
 pkg profiles, method (Target) DebugString() string
@@ -136,10 +124,10 @@
 pkg profiles, type Manager interface { AddFlags, Info, Install, Name, String, Uninstall, VersionInfo }
 pkg profiles, type Manager interface, AddFlags(*flag.FlagSet, Action)
 pkg profiles, type Manager interface, Info() string
-pkg profiles, type Manager interface, Install(*tool.Context, RelativePath, Target) error
+pkg profiles, type Manager interface, Install(*jiri.X, jiri.RelPath, Target) error
 pkg profiles, type Manager interface, Name() string
 pkg profiles, type Manager interface, String() string
-pkg profiles, type Manager interface, Uninstall(*tool.Context, RelativePath, Target) error
+pkg profiles, type Manager interface, Uninstall(*jiri.X, jiri.RelPath, Target) error
 pkg profiles, type Manager interface, VersionInfo() *VersionInfo
 pkg profiles, type MergeAction int
 pkg profiles, type MergePolicies map[string]MergePolicy
@@ -151,7 +139,6 @@
 pkg profiles, type Profile struct, Name string
 pkg profiles, type Profile struct, Root string
 pkg profiles, type ProfilesMode bool
-pkg profiles, type RelativePath struct
 pkg profiles, type Target struct
 pkg profiles, type Target struct, Env Environment
 pkg profiles, type Target struct, InstallationDir string
diff --git a/profiles/commandline/driver.go b/profiles/commandline/driver.go
index 1e9d3f4..9277eb0 100644
--- a/profiles/commandline/driver.go
+++ b/profiles/commandline/driver.go
@@ -12,7 +12,6 @@
 	"bytes"
 	"flag"
 	"fmt"
-	"path/filepath"
 	"strings"
 	"text/template"
 
@@ -111,8 +110,10 @@
 	ArgsLong: "<profiles> is a list of profiles to uninstall.",
 }
 
+// All installed profile data will be stored under profileRoot.
+var profileRoot = jiri.NewRelPath("profiles")
+
 var (
-	rootPath             profiles.RelativePath
 	targetFlag           profiles.Target
 	manifestFlag         string
 	showManifestFlag     bool
@@ -136,8 +137,6 @@
 func Init(defaultManifestFilename string) {
 	targetFlag = profiles.DefaultTarget()
 	mergePoliciesFlag = profiles.JiriMergePolicies()
-	// TODO(toddw): Change logic to derive rootPath from jirix.Root.
-	rootPath = profiles.NewRelativePath("JIRI_ROOT", jiri.FindRoot()).Join("profiles")
 
 	// Every sub-command accepts: --manifest
 	for _, fs := range []*flag.FlagSet{
@@ -329,14 +328,6 @@
 	return out.String()
 }
 
-func handleRelativePath(root profiles.RelativePath, s string) string {
-	// Handle the transition from absolute to relative paths.
-	if filepath.IsAbs(s) {
-		return s
-	}
-	return root.RootJoin(s).Expand()
-}
-
 func fmtInfo(jirix *jiri.X, mgr profiles.Manager, profile *profiles.Profile, target *profiles.Target) (string, error) {
 	if len(infoFlag) > 0 {
 		// Populate an instance listInfo
@@ -356,7 +347,7 @@
 		}
 		info.SchemaVersion = profiles.SchemaVersion()
 		if target != nil {
-			info.Target.InstallationDir = handleRelativePath(rootPath, target.InstallationDir)
+			info.Target.InstallationDir = jiri.NewRelPath(target.InstallationDir).Abs(jirix)
 			info.Target.CommandLineEnv = target.CommandLineEnv().Vars
 			info.Target.Env = target.Env.Vars
 			clenv := ""
@@ -366,7 +357,7 @@
 			info.Target.Command = fmt.Sprintf("jiri v23-profile install --target=%s %s%s", target, clenv, name)
 		}
 		if profile != nil {
-			info.Profile.Root = handleRelativePath(rootPath, profile.Root)
+			info.Profile.Root = profileRoot.Abs(jirix)
 		}
 
 		// Use a template to print out any field in our instance of listInfo.
@@ -466,7 +457,7 @@
 					fmt.Fprintf(jirix.Stdout(), "Updating %s %s from %q to %s\n", n, target, target.Version(), vi)
 				}
 				target.SetVersion(vi.Default())
-				err := mgr.Install(jirix, rootPath, *target)
+				err := mgr.Install(jirix, profileRoot, *target)
 				logResult(jirix, "Update", mgr, *target, err)
 				if err != nil {
 					return err
@@ -489,7 +480,7 @@
 		profile := profiles.LookupProfile(n)
 		for _, target := range profile.Targets() {
 			if vi.IsTargetOlderThanDefault(target.Version()) {
-				err := mgr.Uninstall(jirix, rootPath, *target)
+				err := mgr.Uninstall(jirix, profileRoot, *target)
 				logResult(jirix, "gc", mgr, *target, err)
 				if err != nil {
 					return err
@@ -536,10 +527,10 @@
 			return err
 		}
 	}
-	rp := rootPath.Expand()
-	if exists, err := s.DirectoryExists(rp); err != nil || exists {
-		if err := s.Run("chmod", "-R", "u+w", rp).
-			RemoveAll(rp).Done(); err != nil {
+	d := profileRoot.Abs(jirix)
+	if exists, err := s.DirectoryExists(d); err != nil || exists {
+		if err := s.Run("chmod", "-R", "u+w", d).
+			RemoveAll(d).Done(); err != nil {
 			return err
 		}
 	}
@@ -637,7 +628,7 @@
 	}
 	if err := applyCommand(names, jirix, targetFlag,
 		func(mgr profiles.Manager, jirix *jiri.X, target profiles.Target) error {
-			err := mgr.Install(jirix, rootPath, target)
+			err := mgr.Install(jirix, profileRoot, target)
 			logResult(jirix, "Install:", mgr, target, err)
 			return err
 		}); err != nil {
@@ -661,7 +652,7 @@
 				continue
 			}
 			for _, target := range profile.Targets() {
-				if err := mgr.Uninstall(jirix, rootPath, *target); err != nil {
+				if err := mgr.Uninstall(jirix, profileRoot, *target); err != nil {
 					logResult(jirix, "Uninstall", mgr, *target, err)
 					return err
 				}
@@ -671,7 +662,7 @@
 	} else {
 		applyCommand(args, jirix, targetFlag,
 			func(mgr profiles.Manager, jirix *jiri.X, target profiles.Target) error {
-				err := mgr.Uninstall(jirix, rootPath, target)
+				err := mgr.Uninstall(jirix, profileRoot, target)
 				logResult(jirix, "Uninstall", mgr, target, err)
 				return err
 			})
diff --git a/profiles/env.go b/profiles/env.go
index 3f12f5d..a5788ea 100644
--- a/profiles/env.go
+++ b/profiles/env.go
@@ -172,8 +172,7 @@
 		envs = append(envs, e)
 	}
 	MergeEnv(policies, ch.Vars, envs...)
-	rp := NewRelativePath("JIRI_ROOT", ch.jirix.Root)
-	rp.ExpandEnv(ch.Vars)
+	jiri.ExpandEnv(ch.jirix, ch.Vars)
 }
 
 // SkippingProfiles returns true if no profiles are being used.
diff --git a/profiles/manager.go b/profiles/manager.go
index 0681539..109fa9f 100644
--- a/profiles/manager.go
+++ b/profiles/manager.go
@@ -36,13 +36,10 @@
 
 import (
 	"flag"
-	"path/filepath"
 	"sort"
-	"strings"
 	"sync"
 
 	"v.io/jiri/jiri"
-	"v.io/x/lib/envvar"
 )
 
 var (
@@ -87,71 +84,6 @@
 	return registry.managers[name]
 }
 
-// RelativePath represents a relative path whose root is specified
-// by an environment variable, eg. ${JIRI_ROOT}/profiles/go. It provides
-// access to the 'expanded' value of this variable along with any
-// path components appended to it.
-type RelativePath struct {
-	name  string
-	value string
-	path  string
-}
-
-// NewRelativePath creates a new instance of RelativePath with
-// the variable name as its root and value as the value of the variable.
-func NewRelativePath(name, value string) RelativePath {
-	return RelativePath{name: name, value: value}
-}
-
-// Join returns a copy of RelativePath with the specified components appended
-// to the path using filepath.Join.
-func (rp RelativePath) Join(components ...string) RelativePath {
-	nrp := rp
-	nrp.path = filepath.Join(append([]string{nrp.path}, components...)...)
-	return nrp
-}
-
-// RootJoin returns a copy of RelativePath with the specified components
-// appended to the root using filepath.Join.
-func (rp RelativePath) RootJoin(components ...string) RelativePath {
-	nrp := rp
-	nrp.path = filepath.Join(components...)
-	return nrp
-}
-
-// Expand returns the path with the root variable expanded.
-func (rp RelativePath) Expand() string {
-	return filepath.Join(rp.value, rp.path)
-}
-
-// String returns the RelativePath with the root variable name as the
-// root - i.e. ${name}[/<any append components>].
-func (rp RelativePath) String() string {
-	root := "${" + rp.name + "}"
-	if len(rp.path) == 0 {
-		return root
-	}
-	return root + string(filepath.Separator) + rp.path
-}
-
-// RelativePath returns just the relative path component of RelativePath.
-func (rp RelativePath) RelativePath() string {
-	return rp.path
-}
-
-// ExpandEnv expands all instances of the root variable in the supplied
-// environment.
-func (rp RelativePath) ExpandEnv(env *envvar.Vars) {
-	e := env.ToMap()
-	root := "${" + rp.name + "}"
-	for k, v := range e {
-		n := strings.Replace(v, root, rp.value, -1)
-		if n != v {
-			env.Set(k, n)
-		}
-	}
-}
-
 type Action int
 
 const (
@@ -176,9 +108,9 @@
 	// is its name and version.
 	String() string
 	// Install installs the profile for the specified build target.
-	Install(jirix *jiri.X, root RelativePath, target Target) error
+	Install(jirix *jiri.X, root jiri.RelPath, target Target) error
 	// Uninstall uninstalls the profile for the specified build target. When
 	// the last target for any given profile is uninstalled, then the profile
 	// itself (i.e. the source code) will be uninstalled.
-	Uninstall(jirix *jiri.X, root RelativePath, target Target) error
+	Uninstall(jirix *jiri.X, root jiri.RelPath, target Target) error
 }
diff --git a/profiles/manager_test.go b/profiles/manager_test.go
index b613330..f24a309 100644
--- a/profiles/manager_test.go
+++ b/profiles/manager_test.go
@@ -9,40 +9,12 @@
 	"fmt"
 	"os"
 	"path/filepath"
-	"testing"
 
 	"v.io/jiri/jiri"
 	"v.io/jiri/profiles"
 	"v.io/jiri/tool"
 )
 
-func TestRelativePath(t *testing.T) {
-	rp := profiles.NewRelativePath("VAR", "var")
-	if got, want := rp.Expand(), "var"; got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	if got, want := rp.String(), "${VAR}"; got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	rp = rp.Join("a", "b")
-	if got, want := rp.Expand(), filepath.Join("var", "a", "b"); got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	if got, want := rp.String(), "${VAR}"+string(filepath.Separator)+filepath.Join("a", "b"); got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	rp = rp.Join("x")
-	if got, want := rp.RootJoin("a").Expand(), filepath.Join("var", "a"); got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	if got, want := rp.Join("y").Expand(), filepath.Join("var", "a", "b", "x", "y"); got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-	if got, want := rp.RelativePath(), filepath.Join("a", "b", "x"); got != want {
-		t.Errorf("got %v, want %v", got, want)
-	}
-}
-
 type myNewProfile struct {
 	name, root, status string
 	versionInfo        *profiles.VersionInfo
@@ -82,13 +54,13 @@
 func (p *myNewProfile) AddFlags(*flag.FlagSet, profiles.Action) {
 }
 
-func (p *myNewProfile) Install(jirix *jiri.X, root profiles.RelativePath, target profiles.Target) error {
+func (p *myNewProfile) Install(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
 	p.status = "installed"
 	profiles.AddProfileTarget(p.name, target)
 	return nil
 }
 
-func (p *myNewProfile) Uninstall(jirix *jiri.X, root profiles.RelativePath, target profiles.Target) error {
+func (p *myNewProfile) Uninstall(jirix *jiri.X, root jiri.RelPath, target profiles.Target) error {
 	profiles.RemoveProfileTarget(p.name, target)
 	if profiles.LookupProfile(p.name) == nil {
 		p.status = "uninstalled"
@@ -108,7 +80,7 @@
 	}
 	init()
 
-	rootPath := profiles.NewRelativePath("JIRI_ROOT", ".").Join("profiles")
+	profileRoot := jiri.NewRelPath("profiles")
 	mgr := profiles.LookupManager(myProfile)
 	if mgr == nil {
 		panic("manager not found for: " + myProfile)
@@ -116,7 +88,7 @@
 
 	jirix := &jiri.X{Context: tool.NewDefaultContext()}
 	// Install myNewProfile for target.
-	if err := mgr.Install(jirix, rootPath, target); err != nil {
+	if err := mgr.Install(jirix, profileRoot, target); err != nil {
 		panic("failed to find manager for: " + myProfile)
 	}
 
@@ -142,7 +114,7 @@
 	}
 
 	fmt.Println(mgr.String())
-	mgr.Uninstall(jirix, rootPath, target)
+	mgr.Uninstall(jirix, profileRoot, target)
 	fmt.Println(mgr.String())
 	fmt.Println(mgr.VersionInfo().Supported())
 	fmt.Println(mgr.VersionInfo().Default())
diff --git a/profiles/manifest.go b/profiles/manifest.go
index b044124..0bad100 100644
--- a/profiles/manifest.go
+++ b/profiles/manifest.go
@@ -245,7 +245,6 @@
 	data, err := jirix.Run().ReadFile(filename)
 	if err != nil {
 		if os.IsNotExist(err) {
-			fmt.Fprintf(jirix.Stderr(), "creating %v\n", filename)
 			return nil
 		}
 		return err
diff --git a/profiles/manifest_test.go b/profiles/manifest_test.go
index 855d52c..822a98b 100644
--- a/profiles/manifest_test.go
+++ b/profiles/manifest_test.go
@@ -184,14 +184,6 @@
 	}
 }
 
-func handleRelativePath(root profiles.RelativePath, s string) string {
-	// Handle the transition from absolute to relative paths.
-	if filepath.IsAbs(s) {
-		return s
-	}
-	return root.RootJoin(s).Expand()
-}
-
 func TestReadingV3AndV4(t *testing.T) {
 	fake, cleanup := jiritest.NewFakeJiriRoot(t)
 	defer cleanup()
diff --git a/profiles/util.go b/profiles/util.go
index dd32234..c80ff83 100644
--- a/profiles/util.go
+++ b/profiles/util.go
@@ -194,7 +194,7 @@
 
 // ensureAction ensures that the requested profile and target
 // is installed/uninstalled, installing/uninstalling it if and only if necessary.
-func ensureAction(jirix *jiri.X, action Action, profile string, root RelativePath, target Target) error {
+func ensureAction(jirix *jiri.X, action Action, profile string, root jiri.RelPath, target Target) error {
 	verb := ""
 	switch action {
 	case Install:
@@ -233,13 +233,13 @@
 
 // EnsureProfileTargetIsInstalled ensures that the requested profile and target
 // is installed, installing it if only if necessary.
-func EnsureProfileTargetIsInstalled(jirix *jiri.X, profile string, root RelativePath, target Target) error {
+func EnsureProfileTargetIsInstalled(jirix *jiri.X, profile string, root jiri.RelPath, target Target) error {
 	return ensureAction(jirix, Install, profile, root, target)
 }
 
 // EnsureProfileTargetIsUninstalled ensures that the requested profile and target
 // are no longer installed.
-func EnsureProfileTargetIsUninstalled(jirix *jiri.X, profile string, root RelativePath, target Target) error {
+func EnsureProfileTargetIsUninstalled(jirix *jiri.X, profile string, root jiri.RelPath, target Target) error {
 	return ensureAction(jirix, Uninstall, profile, root, target)
 }