Include the prepared projects list in zuul variables

So that jobs may perform operations on the Zuul-supplied git repos,
add information about the complete set to the job variables.

Change-Id: I0e244c3f310aacac82d7e9f2391739862dad5b6d
diff --git a/doc/source/user/jobs.rst b/doc/source/user/jobs.rst
index 4e1880a..4c8b784 100644
--- a/doc/source/user/jobs.rst
+++ b/doc/source/user/jobs.rst
@@ -207,10 +207,42 @@
 
       .. var:: src_dir
 
-         The path to the source code on the remote host, relative
-         to the home dir of the remote user.
-         E.g., `src/git.example.com/org/project`.
+         The path to the source code relative to the work dir.  E.g.,
+         `src/git.example.com/org/project`.
 
+   .. var:: projects
+      :type: list
+
+      A list of all projects prepared by Zuul for the item.  It
+      includes, at least, the item's own project.  It also includes
+      the projects of any items this item depends on, as well as the
+      projects that appear in :attr:`job.required-projects`.
+
+      This is a list of dictionaries, with each element consisting of:
+
+      .. var:: name
+
+         The name of the project, excluding hostname.  E.g., `org/project`.
+
+      .. var:: short_name
+
+         The name of the project, excluding directories or
+         organizations.  E.g., `project`.
+
+      .. var:: canonical_hostname
+
+         The canonical hostname where the project lives.  E.g.,
+         `git.example.com`.
+
+      .. var:: canonical_name
+
+         The full canonical name of the project including hostname.
+         E.g., `git.example.com/org/project`.
+
+      .. var:: src_dir
+
+         The path to the source code, relative to the work dir.  E.g.,
+         `src/git.example.com/org/project`.
 
    .. var:: tenant
 
diff --git a/zuul/executor/client.py b/zuul/executor/client.py
index 64b635d..fcb6bb2 100644
--- a/zuul/executor/client.py
+++ b/zuul/executor/client.py
@@ -182,6 +182,7 @@
         if (hasattr(item.change, 'newrev') and item.change.newrev
             and item.change.newrev != '0' * 40):
             zuul_params['newrev'] = item.change.newrev
+        zuul_params['projects'] = []  # Set below
         zuul_params['items'] = []
         for i in all_items:
             d = dict()
@@ -200,7 +201,6 @@
                 d['branch'] = i.change.branch
             zuul_params['items'].append(d)
 
-        # Legacy environment variables
         params = dict()
         params['job'] = job.name
         params['timeout'] = job.timeout
@@ -261,6 +261,15 @@
                 params['projects'].append(make_project_dict(project))
                 projects.add(project)
 
+        for p in projects:
+            zuul_params['projects'].append(dict(
+                name=p.name,
+                short_name=p.name.split('/')[-1],
+                canonical_hostname=p.canonical_hostname,
+                canonical_name=p.canonical_name,
+                src_dir=os.path.join('src', p.canonical_name),
+            ))
+
         build = Build(job, uuid)
         build.parameters = params