Allow package to be pinned to same version at multiple paths

Jiri allows the same CIPD package to be included multiple times at
different paths within a checkout. However, it has a (seemingly
arbitrary) restriction that two pins of the same package cannot be at
the same version, because it considers them to be duplicate entries in
the jiri.lock file.

An ideal workaround for this would be to include package paths in
jiri.lock files, but that would require backfilling `path` fields in all
existing lockfiles. The simpler solution is to make jiri less strict by
allowing duplicate (package, tag) entries in lockfiles as long as the
two entries are resolved to the same instance ID.

If the two pins aren't resolved to the same instance ID it would lead to
nondeterminism during the checkout. For example, if package A is pinned
to version:1.0 at paths //src/foo and //src/bar, but the lockfile
contains entries that resolve version:1.0 of package A to two different
instance IDs X and Y, because the lockfile doesn't specify paths,
sometimes instance X would be installed at //src/foo and sometimes
version Y would, depending on the iteration order of the lockfile
manifest.

Change-Id: Iff2f3d8020df737365c25234c7fc49a6b09973f3
Reviewed-on: https://fuchsia-review.googlesource.com/c/jiri/+/1025692
Reviewed-by: Ina Huh <ihuh@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Fuchsia-Auto-Submit: Oliver Newman <olivernewman@google.com>
diff --git a/project/project.go b/project/project.go
index a8fd803..bb09120 100644
--- a/project/project.go
+++ b/project/project.go
@@ -509,7 +509,14 @@
 				LocalPath:   entry["path"],
 			}
 			if v, ok := pkgLocks[pkgLock.Key()]; ok {
-				if v != pkgLock {
+				// HACK: allow the same package to be pinned to the same version
+				// at two different paths by only checking equality of the
+				// InstanceID instead of the entire structs.
+				//
+				// A better way to do this would be to include the `LocalPath`
+				// in the inputs to the PackageLock key, but that would require
+				// adding `path` fields to all existing lockfiles.
+				if v.InstanceID != pkgLock.InstanceID {
 					return nil, nil, fmt.Errorf("package %q has more than 1 version lock %q, %q", pkgName, v.InstanceID, pkgLock.InstanceID)
 				}
 			}