[lockfile] Add optional path field in lockfile to avoid CQ collisions.

Chromium rollers constantly cause CQ collisions due to its roller
logics. This change put optional path field in lockfile to prevent
Chromium rollers competing on the same row of the lockfile. It
should resolve the CQ collisions issue.

Bug: 41089
Change-Id: If07b3b5085b6c01088e5f7a6e711835a0b3ad66b
diff --git a/project/project.go b/project/project.go
index aa25f07..0066aed 100644
--- a/project/project.go
+++ b/project/project.go
@@ -394,6 +394,7 @@
 // PackageLock describes locked version information for a jiri managed package.
 type PackageLock struct {
 	PackageName string `json:"package"`
+	LocalPath   string `json:"path,omitempty"`
 	VersionTag  string `json:"version"`
 	InstanceID  string `json:"instance_id"`
 }
@@ -506,10 +507,13 @@
 		i++
 	}
 	sort.Slice(pkgEntries, func(i, j int) bool {
-		if pkgEntries[i].PackageName == pkgEntries[j].PackageName {
-			return pkgEntries[i].VersionTag < pkgEntries[j].VersionTag
+		if pkgEntries[i].PackageName != pkgEntries[j].PackageName {
+			return pkgEntries[i].PackageName < pkgEntries[j].PackageName
 		}
-		return pkgEntries[i].PackageName < pkgEntries[j].PackageName
+		if pkgEntries[i].LocalPath != pkgEntries[j].LocalPath {
+			return pkgEntries[i].LocalPath < pkgEntries[j].LocalPath
+		}
+		return pkgEntries[i].VersionTag < pkgEntries[j].VersionTag
 	})
 
 	i = 0
@@ -1178,10 +1182,32 @@
 					}
 				}
 			}
+			pkgsWithMultiVersionsMap := make(map[string]map[string]bool)
+			for _, v := range pkgs {
+				versionMap := make(map[string]bool)
+				if _, ok := pkgsWithMultiVersionsMap[v.Name]; ok {
+					versionMap = pkgsWithMultiVersionsMap[v.Name]
+				}
+				versionMap[v.Version] = true
+				pkgsWithMultiVersionsMap[v.Name] = versionMap
+			}
+			for k := range pkgsWithMultiVersionsMap {
+				if len(pkgsWithMultiVersionsMap[k]) <= 1 {
+					delete(pkgsWithMultiVersionsMap, k)
+				}
+			}
 			pkgLocks, err = resolvePackageLocks(jirix, projects, pkgs)
 			if err != nil {
 				return
 			}
+			for _, v := range pkgs {
+				if _, ok := pkgsWithMultiVersionsMap[v.Name]; ok {
+					lockKey := PackageLockKey(v.Name + KeySeparator + v.Version)
+					lockEntry := pkgLocks[lockKey]
+					lockEntry.LocalPath = v.Path
+					pkgLocks[lockKey] = lockEntry
+				}
+			}
 		}
 		return
 	}