Merge "v.io/jiri: remove code that uses tags."
diff --git a/profiles/commandline/driver.go b/profiles/commandline/driver.go
index 5f27d52..94b8380 100644
--- a/profiles/commandline/driver.go
+++ b/profiles/commandline/driver.go
@@ -469,7 +469,7 @@
 		}
 		vi := mgr.VersionInfo()
 		for _, target := range profile.Targets() {
-			if vi.IsNewerThanDefault(target.Version()) {
+			if vi.IsTargetOlderThanDefault(target.Version()) {
 				if verboseFlag {
 					fmt.Fprintf(ctx.Stdout(), "Updating %s %s from %q to %s\n", n, target, target.Version(), vi)
 				}
@@ -484,6 +484,7 @@
 					fmt.Fprintf(ctx.Stdout(), "%s %s at %q is up to date(%s)\n", n, target, target.Version(), vi)
 				}
 			}
+
 		}
 	}
 	return profiles.Write(ctx, manifestFlag)
@@ -495,7 +496,7 @@
 		vi := mgr.VersionInfo()
 		profile := profiles.LookupProfile(n)
 		for _, target := range profile.Targets() {
-			if vi.IsOlderThanDefault(target.Version()) {
+			if vi.IsTargetOlderThanDefault(target.Version()) {
 				err := mgr.Uninstall(ctx, rootPath, *target)
 				logResult(ctx, "gc", mgr, *target, err)
 				if err != nil {
diff --git a/profiles/manager.go b/profiles/manager.go
index 5314174..4f60cfb 100644
--- a/profiles/manager.go
+++ b/profiles/manager.go
@@ -10,11 +10,10 @@
 // SDKs. Profiles thus refer to uncompiled source code that needs to be compiled
 // for a specific "target". Targets represent compiled code and consist of:
 //
-// 1. A 'tag' that can be used a short hand for refering to a target
-// 2. An 'architecture' that refers to the CPU to be generate code for
-// 3. An 'operating system' that refers to the operating system to generate
+// 1. An 'architecture' that refers to the CPU to be generate code for
+// 2. An 'operating system' that refers to the operating system to generate
 //    code for.
-// 4. An 'environment' which is a set of environment variables to use when
+// 3. An 'environment' which is a set of environment variables to use when
 //    compiling and using the profile.
 //
 // Targets provide the essential support for cross compilation.
@@ -27,9 +26,8 @@
 // Profiles may be installed, updated or removed. When doing so, the name of
 // the profile is required, but the other components of the target are optional
 // and will default to the values of the system that the commands are run on
-// (so-called native builds). Once a profile is installed it may be referred to
-// by its tag for subsequent updates and removals. These operations are
-// defined by the profiles.Manager interface.
+// (so-called native builds). These operations are defined by the
+// profiles.Manager interface.
 //
 // The manifest tracks the installed profiles and their configurations.
 // Other command line tools and packages are expected read information about
diff --git a/profiles/manager_test.go b/profiles/manager_test.go
index 400fe7e..5e83747 100644
--- a/profiles/manager_test.go
+++ b/profiles/manager_test.go
@@ -148,10 +148,10 @@
 
 	// Output:
 	// Profile: myNewProfile: installed
-	// [=arm-linux@1]
+	// [arm-linux@1]
 	//
 	// Profile: myNewProfile: installed
-	// [=arm-linux@1]
+	// [arm-linux@1]
 	//
 	// Profile: myNewProfile: uninstalled
 	//
diff --git a/profiles/manifest.go b/profiles/manifest.go
index 91f798c..4631ac6 100644
--- a/profiles/manifest.go
+++ b/profiles/manifest.go
@@ -41,8 +41,11 @@
 }
 
 func (p *Profile) Targets() OrderedTargets {
-	r := make(OrderedTargets, len(p.targets))
-	copy(r, p.targets)
+	r := make(OrderedTargets, len(p.targets), len(p.targets))
+	for i, t := range p.targets {
+		tmp := *t
+		r[i] = &tmp
+	}
 	return r
 }
 
@@ -60,7 +63,9 @@
 }
 
 type targetSchema struct {
-	XMLName         xml.Name    `xml:"target"`
+	XMLName xml.Name `xml:"target"`
+	// TODO(cnicolaou): remove this after this CL is checked in and no-one
+	// is using Tags.
 	Tag             string      `xml:"tag,attr"`
 	Arch            string      `xml:"arch,attr"`
 	OS              string      `xml:"os,attr"`
@@ -103,7 +108,7 @@
 }
 
 // LookupProfileTarget returns the target information stored for the name
-// profile. Typically, the target parameter will contain just the Tag field.
+// profile.
 func LookupProfileTarget(name string, target Target) *Target {
 	mgr := db.profile(name)
 	if mgr == nil {
@@ -163,8 +168,10 @@
 	defer pdb.Unlock()
 	target.UpdateTime = time.Now()
 	if pi, present := pdb.db[name]; present {
-		if existing := FindTargetByTag(pi.targets, target); existing != nil {
-			return fmt.Errorf("tag %q is already used by profile: %v, existing target: %v", target.tag, name, existing)
+		for _, t := range pi.Targets() {
+			if target.Match(t) {
+				return fmt.Errorf("%s is already used by profile %s %s", target, name, pi.Targets())
+			}
 		}
 		pi.targets = InsertTarget(pi.targets, target)
 		return nil
@@ -257,7 +264,6 @@
 		}
 		for _, target := range profile.Targets {
 			pdb.db[name].targets = append(pdb.db[name].targets, &Target{
-				tag:             target.Tag,
 				arch:            target.Arch,
 				opsys:           target.OS,
 				Env:             target.Env,
@@ -290,13 +296,9 @@
 			if len(target.version) == 0 {
 				return fmt.Errorf("missing version for profile %s target: %s", name, target)
 			}
-			// TODO(cnicolaou): enable this in a subsequent CL.
-			//if len(target.tag) > 0 {
-			//	return fmt.Errorf("tags are no longer supported - the following profile and target has one: %s %s", name, target)
-			//}
 			schema.Profiles[i].Targets = append(schema.Profiles[i].Targets,
 				&targetSchema{
-					Tag:             target.tag,
+					Tag:             "",
 					Arch:            target.arch,
 					OS:              target.opsys,
 					Env:             target.Env,
diff --git a/profiles/target.go b/profiles/target.go
index a24fcb9..cffcbd9 100644
--- a/profiles/target.go
+++ b/profiles/target.go
@@ -16,17 +16,15 @@
 )
 
 // Target represents specification for the environment that the profile is
-// to be built for. Target may be named (via its tag), see the Match
-// method for a definition of how Targets are compared.
-// Targets include a version string to allow for upgrades and for
-// the simultaneous existence of incompatible versions.
+// to be built for. Targets include a version string to allow for upgrades and
+// for the simultaneous existence of incompatible versions.
 //
 // Target and Environment implement flag.Getter so that they may be used
 // with the flag package. Two flags are required, one to specify the target
-// in <tag>=<arch>-<os>@<version> format and a second to specify environment
+// in <arch>-<os>@<version> format and a second to specify environment
 // variables either as comma separated values or as repeated arguments.
 type Target struct {
-	tag, arch, opsys, version string
+	arch, opsys, version string
 	// The environment as specified on the command line
 	commandLineEnv Environment
 	// The environment as modified by a profile implementation
@@ -36,11 +34,6 @@
 	isSet           bool
 }
 
-// Tag returns the tag, if any, for this target.
-func (pt *Target) Tag() string {
-	return pt.tag
-}
-
 // Arch returns the archiecture of this target.
 func (pt *Target) Arch() string {
 	return pt.arch
@@ -78,7 +71,7 @@
 }
 
 // TargetSpecificDirname returns a directory name that is specific
-// to that target taking account the tag, architecture, operating system and
+// to that target taking account the architecture, operating system and
 // command line environment variables, if relevant, into account (e.g
 // GOARM={5,6,7}).
 func (pt *Target) TargetSpecificDirname() string {
@@ -111,17 +104,12 @@
 
 // Match returns true if pt and pt2 meet the following criteria in the
 // order they are listed:
-// - if both targets have a non-zero length Tag field that is
-//   identical
 // - if the Arch and OS fields are exactly the same
 // - if pt has a non-zero length Version field, then it must be
 //   the same as that in pt2
 // Match is used by the various methods and functions in this package
 // when looking up Targets unless otherwise specified.
 func (pt Target) Match(pt2 *Target) bool {
-	if len(pt.tag) > 0 && len(pt2.tag) > 0 {
-		return pt.tag == pt2.tag
-	}
 	if pt.arch != pt2.arch || pt.opsys != pt2.opsys {
 		return false
 	}
@@ -132,15 +120,14 @@
 }
 
 // Less returns true if pt2 is considered less than pt. The ordering
-// takes into account only the tag, architecture, operating system and version of
+// takes into account only the architecture, operating system and version of
 // the target. The architecture and operating system are ordered
 // lexicographically in ascending order, then the version is ordered but in
 // descending lexicographic order except that the empty string is considered
-// the 'highest' value, finally the tag is used to order in ascending order.
-// Thus, (targets in [<tag>=]<arch>-<os>[@<version>] format), are all true:
+// the 'highest' value.
+// Thus, (targets in <arch>-<os>[@<version>] format), are all true:
 // b-c < c-c
 // b-c@3 < b-c@2
-// a-b@3 < foo=a-b@3
 //
 func (pt *Target) Less(pt2 *Target) bool {
 	switch {
@@ -154,8 +141,6 @@
 		return false
 	case pt.version != pt2.version:
 		return pt.version > pt2.version
-	case pt.tag != pt2.tag:
-		return pt.tag < pt2.tag
 	default:
 		return false
 	}
@@ -169,7 +154,7 @@
 
 // Usage returns the usage string for Target.
 func (pt *Target) Usage() string {
-	return "specifies a profile target in the following form: <arch>-<os>[@<version>]|<tag>[@version]|<tag>=<arch>-<val>[@<version>]"
+	return "specifies a profile target in the following form: <arch>-<os>[@<version>]|<arch>-<val>[@<version>]"
 }
 
 // Set implements flag.Value.
@@ -179,25 +164,10 @@
 		t.version = val[index+1:]
 		val = val[:index]
 	}
-	index = strings.IndexByte(val, '=')
-	tag := ""
-	if index > -1 {
-		tag = val[0:index]
-		val = val[index+1:]
-	} else {
-		if strings.IndexByte(val, '-') < 0 {
-			t.tag = val
-			t.arch = ""
-			t.opsys = ""
-			t.isSet = true
-			return nil
-		}
-	}
 	parts := strings.Split(val, "-")
 	if len(parts) != 2 || (len(parts[0]) == 0 || len(parts[1]) == 0) {
-		return fmt.Errorf("%q doesn't look like [tag=]<arch>-<os>", val)
+		return fmt.Errorf("%q doesn't look like <arch>-<os>[@<version>]", val)
 	}
-	t.tag = tag
 	t.arch = parts[0]
 	t.opsys = parts[1]
 	t.isSet = true
@@ -211,7 +181,6 @@
 		arch, isSet := goarch()
 		return Target{
 			isSet:   isSet,
-			tag:     "",
 			arch:    arch,
 			opsys:   runtime.GOOS,
 			version: t.version,
@@ -264,7 +233,7 @@
 // String implements flag.Getter.
 func (pt Target) String() string {
 	v := pt.Get().(Target)
-	return fmt.Sprintf("%v=%v-%v@%s", v.tag, v.arch, v.opsys, v.version)
+	return fmt.Sprintf("%v-%v@%s", v.arch, v.opsys, v.version)
 }
 
 // OrderderTargets is a list of *Targets ordered by architecture,
@@ -293,7 +262,7 @@
 // DebugString returns a pretty-printed representation of pt.
 func (pt Target) DebugString() string {
 	v := pt.Get().(Target)
-	return fmt.Sprintf("%v=%v-%v@%s dir:%s --env=%s envvars:%v", v.tag, v.arch, v.opsys, v.version, pt.InstallationDir, strings.Join(pt.commandLineEnv.Vars, ","), pt.Env.Vars)
+	return fmt.Sprintf("%v-%v@%s dir:%s --env=%s envvars:%v", v.arch, v.opsys, v.version, pt.InstallationDir, strings.Join(pt.commandLineEnv.Vars, ","), pt.Env.Vars)
 }
 
 // Set implements flag.Getter.
@@ -350,8 +319,9 @@
 }
 
 // FindTarget returns the first target that matches the requested target from
-// the slice of Targets; note that the requested target need only include a
-// tag name. It returns nil if the requested target does not exist.
+// the slice of Targets. If target has not been explicitly set and there is
+// only a single target available in targets then that one target is considered
+// as matching.
 func FindTarget(targets OrderedTargets, target *Target) *Target {
 	if len(targets) == 1 && !target.IsSet() {
 		tmp := *targets[0]
@@ -376,17 +346,3 @@
 	}
 	return FindTarget(targets, target)
 }
-
-// FindTargetByTag searches targets to see if any have the same
-// tag as the target parameter, and if so, return that target.
-func FindTargetByTag(targets OrderedTargets, target *Target) *Target {
-	if len(target.tag) == 0 {
-		return nil
-	}
-	for _, t := range targets {
-		if target.tag == t.tag {
-			return t
-		}
-	}
-	return nil
-}
diff --git a/profiles/target_test.go b/profiles/target_test.go
index f55cd5b..f0404f1 100644
--- a/profiles/target_test.go
+++ b/profiles/target_test.go
@@ -19,28 +19,26 @@
 	var target profiles.Target
 	flags := flag.NewFlagSet("test", flag.ContinueOnError)
 	profiles.RegisterTargetAndEnvFlags(flags, &target)
-	flags.Parse([]string{"--target=name=arm-linux", "--env=A=B,C=D", "--env=E=F"})
+	flags.Parse([]string{"--target=arm-linux", "--env=A=B,C=D", "--env=E=F"})
 	fmt.Println(target.String())
 	fmt.Println(target.DebugString())
 	// Output:
-	// name=arm-linux@
-	// name=arm-linux@ dir: --env=A=B,C=D,E=F envvars:[]
+	// arm-linux@
+	// arm-linux@ dir: --env=A=B,C=D,E=F envvars:[]
 }
 
 func TestProfileTargetArgs(t *testing.T) {
 	for i, c := range []struct {
-		arg, tag, arch, os string
-		err                bool
+		arg, arch, os, version string
+		err                    bool
 	}{
-		{"a-b", "", "a", "b", false},
-		{"t=a-b", "t", "a", "b", false},
-		{"a", "a", "", "", false},
+		{"a-b", "a", "b", "", false},
+		{"a-b@3", "a", "b", "3", false},
 		{"", "", "", "", true},
+		{"a", "", "", "", true},
 		{"a-", "", "", "", true},
 		{"-a", "", "", "", true},
-		{"t=a", "", "", "", true},
-		{"t=a-", "", "", "", true},
-		{"t=-a", "", "", "", true},
+		{"a-", "", "", "", true},
 	} {
 		target := &profiles.Target{}
 		if err := target.Set(c.arg); err != nil {
@@ -49,9 +47,6 @@
 			}
 			continue
 		}
-		if got, want := target.Tag(), c.tag; got != want {
-			t.Errorf("%d: got %v, want %v", i, got, want)
-		}
 		if got, want := target.Arch(), c.arch; got != want {
 			t.Errorf("%d: got %v, want %v", i, got, want)
 		}
@@ -112,9 +107,6 @@
 		equal        bool
 	}{
 		{s{""}, s{""}, true},
-		{s{"--t=tag"}, s{"--t=tag"}, true},
-		{s{"--t=tag"}, s{"--t=tag2"}, false},
-		{s{"--t=tag=a-b"}, s{"--t=tag=c-d"}, true}, // tag trumps all else.
 		{s{"--t=a-b"}, s{"--t=a-b"}, true},
 		{s{"--t=a-b@foo"}, s{"--t=a-b@foo"}, true},
 		{s{"--t=a-b@foo"}, s{"--t=a-b"}, false},
@@ -149,17 +141,17 @@
 
 func TestTargetVersion(t *testing.T) {
 	t1, t2 := &profiles.Target{}, &profiles.Target{}
-	t1.Set("tag=cpu,os")
-	t2.Set("tag=cpu,os")
+	t1.Set("cpu,os")
+	t2.Set("cpu,os")
 	if got, want := t1.Match(t2), true; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
-	t2.Set("tag=cpu,os@var")
+	t2.Set("cpu,os@var")
 	if got, want := t1.Match(t2), true; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
-	t2.Set("tag=cpu,os")
-	t1.Set("tag=cpu,os@baz")
+	t2.Set("cpu,os")
+	t1.Set("cpu,os@baz")
 	if got, want := t1.Match(t2), false; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
@@ -167,19 +159,19 @@
 
 func TestDefaults(t *testing.T) {
 	t1 := &profiles.Target{}
-	native := fmt.Sprintf("=%s-%s@", runtime.GOARCH, runtime.GOOS)
+	native := fmt.Sprintf("%s-%s@", runtime.GOARCH, runtime.GOOS)
 	if got, want := t1.String(), native; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
-	t1.Set("tag=cpu-os")
-	if got, want := t1.String(), "tag=cpu-os@"; got != want {
+	t1.Set("cpu-os")
+	if got, want := t1.String(), "cpu-os@"; got != want {
 		t.Errorf("got %v, want %v", got, want)
 	}
 }
 
 func TestFindTarget(t *testing.T) {
 	t1 := &profiles.Target{}
-	t1.Set("bar=a-o")
+	t1.Set("a-o")
 	ts := []*profiles.Target{t1}
 	prev := os.Getenv("GOARCH")
 	if len(prev) > 0 {
@@ -192,14 +184,14 @@
 		t.Errorf("got %v, want %v", got, want)
 	}
 	t2 := &profiles.Target{}
-	t2.Set("baz=a-o1")
+	t2.Set("a-o1")
 	ts = append(ts, t2)
 	if got := profiles.FindTarget(ts, &def); got != nil {
 		t.Errorf("got %v, want nil", got)
 	}
 
 	w := &profiles.Target{}
-	w.Set("bar")
+	w.Set("a-o")
 	if got, want := profiles.FindTarget(ts, w), t1; !got.Match(want) {
 		t.Errorf("got %v, want %v", got, want)
 	}
@@ -209,9 +201,9 @@
 		t.Errorf("got %v, want %v", got, want)
 	}
 
-	w.Set("baz=a-o")
-	if got, want := profiles.FindTarget(ts, w), t2; !got.Match(want) {
-		t.Errorf("got %v, want %v", got, want)
+	w.Set("c-d")
+	if got := profiles.FindTarget(ts, w); got != nil {
+		t.Errorf("got %v, want nil", got)
 	}
 }
 
@@ -245,7 +237,7 @@
 	}
 
 	ol := profiles.OrderedTargets{}
-	data := []string{"a-b@2", "x-y", "a-b@12", "a-b@3", "foo=a-b@3", "a-b@0", "x-y@3", "tag=x-y@2"}
+	data := []string{"a-b@2", "x-y", "a-b@12", "a-b@3", "a-b@0", "x-y@3", "x-y@2"}
 	for _, s := range data {
 		target, err := profiles.NewTarget(s)
 		if err != nil {
@@ -262,10 +254,10 @@
 			t.Errorf("%v is not less than %v", ol[i], ol[j])
 		}
 	}
-	if got, want := ol[0].String(), "=a-b@3"; got != want {
+	if got, want := ol[0].String(), "a-b@3"; got != want {
 		t.Fatalf("got %v, want %v", got, want)
 	}
-	if got, want := ol[len(ol)-1].String(), "tag=x-y@2"; got != want {
+	if got, want := ol[len(ol)-1].String(), "x-y@2"; got != want {
 		t.Fatalf("got %v, want %v", got, want)
 	}
 	t2, _ := profiles.NewTarget("a-b@12")
diff --git a/profiles/versions.go b/profiles/versions.go
index 0885783..9a3b492 100644
--- a/profiles/versions.go
+++ b/profiles/versions.go
@@ -104,14 +104,14 @@
 	return r
 }
 
-// IsNewerThanDefault returns true if the supplied version is newer than the
-// default.
-func (vi *VersionInfo) IsNewerThanDefault(version string) bool {
+// IsTargetNewerThanDefault returns true if the supplied version is newer than
+// the default.
+func (vi *VersionInfo) IsTargetNewerThanDefault(version string) bool {
 	return vi.defaultVersion < version
 }
 
-// IsOlderThanDefault returns true if the supplied version is older than the
-// default.
-func (vi *VersionInfo) IsOlderThanDefault(version string) bool {
+// IsTargetOlderThanDefault returns true if the supplied version is older than
+// the default.
+func (vi *VersionInfo) IsTargetOlderThanDefault(version string) bool {
 	return vi.defaultVersion > version
 }