Do git submodule preparation in git

Ansible's performance was disappointing, so let's try to see if I can do
it better in pure shell. `jq` provides access to the repository
structure as exported from Zuul's variable via an intermediate JSON
file.

Change-Id: If420fe6f39eb29f8791551b7240938bbdc5d66b3
diff --git a/playbooks/git-submodules/run.yaml b/playbooks/git-submodules/run.yaml
index 475d677..27a7948 100644
--- a/playbooks/git-submodules/run.yaml
+++ b/playbooks/git-submodules/run.yaml
@@ -1,32 +1,32 @@
 - hosts: all
   tasks:
+    - name: Prepare git submodules
+      shell: |
+        set -ex
 
-    - name: Point the "origin" git remote to its filesystem location
-      shell: git config --get remote.origin.url > /dev/null && git config remote.origin.url "{{ ansible_user_dir }}/{{ item.src_dir}}" || true
-      args:
-        chdir: "{{ ansible_user_dir }}/{{ item.src_dir}}"
-      with_items: "{{ zuul.projects.values() | list }}"
+        jq -r '.projects | .[] | .src_dir ' ~/zuul-env.json | while read PROJECT; do
+          pushd "{{ ansible_user_dir }}/${PROJECT}"
+          # 1) Adjust the origin's URL so that it points to its filesystem location.
+          # This makes relative URLs in submodules work.
+          git config --get remote.origin.url > /dev/null && git config remote.origin.url "{{ ansible_user_dir }}/${PROJECT}" || true
+          # 2) Prepare an alias for each repository, appending the .git suffix.
+          # E.g. Boost uses submodule URLs which end with a .git trailing suffix.
+          # That happens to be handled by many git servers automagically.
+          # Instead of rewriting the submodule URLs within each repo (which would either mark
+          # the repo dirty, or change its hash), use a big hammer and provide these
+          # "compatibility" repository names.
+          # If both a `repo` and `repo.git` already exist, then we're screwed.
+          ln -s $(basename "${PROJECT}") ../$(basename "${PROJECT}").git
+          popd
+        done
 
-    # E.g. Boost uses submodule URLs which end with a .git trailing suffix.
-    # That happens to be handled by many git servers automagically.
-    # Instead of rewriting the submodule URLs within each repo (which would either mark
-    # the repo dirty, or change its hash), use a big hammer and provide these
-    # "compatibility" repository names.
-    # If both a `repo` and `repo.git` already exist, then we're screwed.
-    - name: Prepare path/to/foo.git repository aliases for each path/to/foo repository
-      file:
-        src: "{{ ansible_user_dir }}/{{ item.src_dir}}"
-        dest: "{{ ansible_user_dir }}/{{ item.src_dir}}.git"
-        state: link
-      with_items: "{{ zuul.projects.values() | list }}"
+        # 3) Update submodules via calling out to git
+        cd "$(jq -r '.project.src_dir' ~/zuul-env.json)"
+        git submodule update --init --recursive
 
-    - name: Recursively prepare git submodules of the main project
-      shell: git submodule update --init --recursive
-      args:
-        chdir: "{{ ansible_user_dir }}/{{ zuul.project.src_dir}}"
-
-    - name: Set the "origin" git remote back to Zuul's fake /dev/null
-      shell: git config --get remote.origin.url > /dev/null && git config remote.origin.url file:///dev/null || true
-      args:
-        chdir: "{{ ansible_user_dir }}/{{ item.src_dir}}"
-      with_items: "{{ zuul.projects.values() | list }}"
+        # 4) Undo changes made in step 1
+        jq -r '.projects | .[] | .src_dir ' ~/zuul-env.json | while read PROJECT; do
+          pushd "{{ ansible_user_dir }}/${PROJECT}"
+          git config --get remote.origin.url > /dev/null && git config remote.origin.url file:///dev/null || true
+          popd
+        done