Index: appengine/swarming/server/task_request.py |
diff --git a/appengine/swarming/server/task_request.py b/appengine/swarming/server/task_request.py |
index e4a8062c94bbba0b4a7ea3af7a3fa85dacc37e3f..8b7a5cc1f1882ae1eda42a2a82671711924e0f85 100644 |
--- a/appengine/swarming/server/task_request.py |
+++ b/appengine/swarming/server/task_request.py |
@@ -333,11 +333,40 @@ class CipdInput(ndb.Model): |
package_names.add(p.package_name) |
self.packages.sort(key=lambda p: p.package_name) |
- def packages_grouped_by_path(self): |
- """Returns sorted [(path), [package]) list. Used by user_task.html.""" |
+ def packages_grouped_by_path(self, pins): |
+ """Returns sorted [(path, [PinInfo, ...])]. |
+ |
+ PinInfo is a namedtuple with two fields 'pkg' and 'pin'. 'pkg' is the |
+ CipdPackage that was specified in the task request. 'pin' is the CipdPackage |
+ that was resolved by the bot at runtime, and contains a full package name as |
+ well as a package instance id. |
+ |
+ If pinning information is unavailable, or if 'pkg' already specifies a full |
+ pin, 'pin' is None. If 'version' or 'package_name' are the same between |
+ 'pkg' and 'pin', then the field in 'pin' is None. |
+ |
+ Args: |
+ pins - a list of CipdPackages which represent the pin counterparts of |
+ self.packages. |
+ |
+ Used by user_task.html. |
+ """ |
+ assert pins is None or len(pins) == len(self.packages) |
+ PinInfo = collections.namedtuple('PinInfo', ['pkg', 'pin']) |
+ pinned = pins is not None |
+ |
packages = collections.defaultdict(list) |
- for p in self.packages: |
- packages[p.path].append(p) |
+ for i, pkg in enumerate(self.packages): |
+ pin = None |
+ if pinned: |
+ pin = pins[i] |
+ if pkg.package_name == pin.package_name: |
+ pin.package_name = None |
+ if pkg.version == pin.version: |
+ pin.version = None |
+ if pin.package_name is None and pin.version is None: |
+ pin = None |
+ packages[pkg.path].append(PinInfo(pkg, pin)) |
for pkgs in packages.itervalues(): |
pkgs.sort() |
return sorted(packages.iteritems()) |