fetch-and-push-remote: Allow prefixing imported remote branches

Importing upstream Codelinaro/CodeAurora branches is becoming
unmaintainable from Gerrit ACL perspective; we can't possibly list all
different branch names they use; and a regex for matching them is
getting too complex to be safe to use.

Allow prefixing those branches instead, like "clo/*" or "caf/*", so that
ACLs can be defined for those prefixes instead.

Change-Id: I79f3fff69c395e68a46f2d72bd41f6f13676c8ad
diff --git a/bin/fetch-and-push-remote b/bin/fetch-and-push-remote
index 7018394..0b4bac1 100755
--- a/bin/fetch-and-push-remote
+++ b/bin/fetch-and-push-remote
@@ -33,6 +33,7 @@
 export DEBUG=
 export DRY_RUN=false
 export NEW_TAG_ANNOTATION_MESSAGE=
+export PUSH_BRANCH_PREFIX=
 export PUSH_SKIP_VALIDATION=false
 export TRY_QUALIFYING_REFS=false
 
@@ -69,6 +70,8 @@
 $0 [-u|--url MANIFEST_URL] [-b|--manifest-branch] [-m|--manifest MANIFEST]
 [-nb|--new-branch NEW_BRANCH] [-rb|--remote-branch REMOTE_BRANCH TARGET_BRANCH]
 [-nt|--new-tag NEW_TAG] [-rt|--remote-tag REMOTE_TAG]
+[--push-current-remote-rev|--push-current-upstream-rev]
+[--push-with-branch-prefix PUSH_BRANCH_PREFIX]
 [-g|--groups "<group1>,..."] [-p|--projects "project1 project2"] [-d|--debug]
 [-n|--dry-run] [-s|--skip-init] [--push-skip-validation] [--repo-url REPO_URL]
 [--depth REPO_DEPTH] [--force-sync] [-j|--jobs REPO_NUM_JOBS] [-h|--help]
@@ -108,12 +111,20 @@
                                   project. This allows to push the current state
                                   when different tags or branches are used
                                   across projects.
+                                  See also --push-with-branch-prefix.
 --push-current-upstream-rev     : Push revisions that are listed as 'upstream'
                                   in the manifest xml attributes. This allows
                                   syncing from a release manifest (with
                                   'revision' attribute pointing to commit
                                   sha1's) that also defines upstream branches in
                                   the 'upstream' attributes.
+                                  See also --push-with-branch-prefix.
+--push-with-branch-prefix PUSH_BRANCH_PREFIX
+                                : Prepend "PUSH_BRANCH_PREFIX" to branch names
+                                  when importing upstream branches. Allows
+                                  grouping various upstream under one naming
+                                  scheme that's easy to match, e.g., for Gerrit
+                                  ACLs. Example: "clo/" for CodeLinaro branches.
 --try-qualifying-refs           : When using "--push-current-remote-rev" and
                                   manifest (remote) revisions are unqualified,
                                   query remote heads and tags to find the
@@ -374,6 +385,7 @@
 #
 # Globals:
 #   DRY_RUN
+#   PUSH_BRANCH_PREFIX
 #   PUSH_SKIP_VALIDATION
 #   REPO_PROJECT
 #   REPO_REMOTE
@@ -397,6 +409,7 @@
 # Push current upstream revisions to the target gerrit
 #
 # Globals:
+#   PUSH_BRANCH_PREFIX
 #   PUSH_SKIP_VALIDATION
 #   TARGET_GERRIT_NAME
 #   TRY_QUALIFYING_REFS
@@ -519,6 +532,10 @@
             PUSH_CURRENT_UPSTREAM_REVISION=true
             shift 1
             ;;
+        --push-with-branch-prefix)
+            PUSH_BRANCH_PREFIX="$2"
+            shift 2
+            ;;
         --try-qualifying-refs)
             export TRY_QUALIFYING_REFS=true
             shift 1
diff --git a/shell-libs/repo-forall-functions.sh b/shell-libs/repo-forall-functions.sh
index 90965b4..0ac6d79 100644
--- a/shell-libs/repo-forall-functions.sh
+++ b/shell-libs/repo-forall-functions.sh
@@ -513,6 +513,7 @@
 #
 # Globals:
 #   DRY_RUN
+#   PUSH_BRANCH_PREFIX
 #   PUSH_SKIP_VALIDATION
 #   REPO_REMOTE
 #   TARGET_GERRIT_NAME
@@ -530,6 +531,10 @@
         log_e "Cannot push current revision on project ${REPO_PROJECT};" \
             "cannot resolve target reference."
     fi
+    if [[ "${target_ref}" == refs/heads/* ]]; then
+        local branch_name="${target_ref/refs\/heads\//}"
+        target_ref="refs/heads/${PUSH_BRANCH_PREFIX}${branch_name}"
+    fi
     _git_push "${REPO_LREV}:${target_ref}"
 }
 
@@ -537,6 +542,8 @@
 # Push the remote revision that the manifest is currently pointing to.
 #
 # Globals:
+#   DRY_RUN
+#   PUSH_BRANCH_PREFIX
 #   REPO_PROJECT
 #   REPO_REMOTE
 #   REPO_UPSTREAM
@@ -553,9 +560,9 @@
             "a (release) manifest that has 'upstream' attributes defined."
     fi
 
-    local target_ref
+    local upstream_ref
     local result=0
-    target_ref=$(_qualify_remote_ref "${REPO_UPSTREAM}") || result=$?
+    upstream_ref=$(_qualify_remote_ref "${REPO_UPSTREAM}") || result=$?
     if [ "${result}" -ne 0 ]; then
         log_e "Cannot push upstream revision on project ${REPO_PROJECT};" \
             "cannot resolve target reference ${REPO_UPSTREAM}."
@@ -563,19 +570,23 @@
 
     # remove_shallow_clone works on REPO_RREV, so we can't use it here.
     if [ -f .git/shallow ] ; then
-        _git_fetch "${target_ref}:${target_ref}"
+        _git_fetch "${upstream_ref}:${upstream_ref}"
     fi
 
     local src_ref
-    if [[ "${target_ref}" == refs/tags/* ]]; then
-        src_ref="${target_ref}"
-    elif [[ "${target_ref}" == refs/heads/* ]]; then
+    local target_ref
+    if [[ "${upstream_ref}" == refs/tags/* ]]; then
+        src_ref="${upstream_ref}"
+        target_ref="${upstream_ref}"
+    elif [[ "${upstream_ref}" == refs/heads/* ]]; then
+        local branch_name="${upstream_ref/refs\/heads\//}"
         # See case of SC2030 above.
         # shellcheck disable=SC2031
-        src_ref="${REPO_REMOTE}/${target_ref/refs\/heads\//}"
+        src_ref="${REPO_REMOTE}/${branch_name}"
+        target_ref="refs/heads/${PUSH_BRANCH_PREFIX}${branch_name}"
     else
         log_e "Can't resolve source ref from ${REPO_UPSTREAM}, resolved to" \
-            "${target_ref}."
+            "${upstream_ref}."
     fi
 
     _git_push "${src_ref}:${target_ref}"