Remove unnecessary spaces quoting
[hvutilities.git] / scripts / git-hg-sub-import
index ecd7757..9d6ae49 100755 (executable)
@@ -7,26 +7,159 @@ set -o errexit
 # Uncomment to have verbose debug output
 #debug=1
 
+PROJRC_COUNT=0
+SUBPATHS_COUNT=0
+
 print_usage()
 {
     echo "$(basename $0) -- HG subrepository importer for git-remote-hg"
     echo "Usage: $(basename $0) [OPTIONS...]"
 }
 
-# git-remote-hg doesn't work with Mercurial subpaths extension,
-# so use it manually
-hg_subpaths_config() {
-    subpaths=$(hg showconfig | grep "subpaths")
+# We parse the projrc file in the assembly (on the server), to check
+# for any projrc substitutions.
+#
+# Arg 1: repository (path and name)
+#
+# Return the substitution key/values in arrays:
+#  PROJRC_KEY
+#  PROJRC_VAL
+# PROJRC_COUNT will be greater than zero if any substitutions were found.
+hg_parse_projrc() {
+    if [ ${#} -lt 1 ]; then
+        echo "Missing repository name"
+    fi
+
+    # Repo name can have spaces in it, hence the use of ${*}
+    local repo="${*}"
+
+    if [ -f "${repo}/.hg/projrc" ]; then
+
+        TMPF="/tmp/$(basename $0).projrc-$$.tmp"
+
+        # Create temporary copy to replace backslashes with slashes.
+        # Make sure to only replace path backslashes, not backslashes for
+        # quoting spaces.
+        # \\[^ ]  Match a backslash, not followed by a space
+        cat "${repo}/.hg/projrc" | sed 's/\\\([^ ]\)/\/\1/g' > ${TMPF}
+
+        while read p; do
+            if echo ${p} | grep -q "\s=\s"; then
+                local key=$(echo ${p} | sed 's/^\(.*\) = .*/\1/')
+                local val=$(echo ${p} | sed 's/.* = \(.*\)/\1/')
+
+                PROJRC_KEY[${PROJRC_COUNT}]="${key}"
+                PROJRC_VAL[${PROJRC_COUNT}]="${val}"
+
+                if [ -n "${debug}" ]; then
+                    echo "Parsing PROJRC entry: ${p}"
+                    echo "  key: ${key}"
+                    echo "  val: ${val}"
+                fi
+
+                PROJRC_COUNT=$((PROJRC_COUNT + 1))
+            fi
+        done < ${TMPF}
+
+        rm ${TMPF}
+    fi
+}
+
+# We parse the Mercurial configuration, to check
+# for any SUBPATHS substitutions.
+#
+# Return the substitution key/values in arrays:
+#  SUBPATHS_KEY
+#  SUBPATHS_VAL
+# SUBPATHS_COUNT will be greater than zero if any substitutions were found.
+hg_parse_subpaths() {
+    subpaths=$(hg showconfig subpaths)
+
+    if [ -n "${subpaths}" ]; then
+        for p in ${subpaths}; do
+            local key=$(echo ${p} | sed 's/^subpaths\.\(.*\)=.*/\1/')
+            local val=$(echo ${p} | sed 's/.*=\(.*\)/\1/')
+
+            # Replace '\\' with '/'
+            key=${key//\\\\/\/}
+            #        ^^ replace multiple times
+
+            val=${val//\\\\/\/}
+
+            SUBPATHS_KEY[${SUBPATHS_COUNT}]="${key}"
+            SUBPATHS_VAL[${SUBPATHS_COUNT}]="${val}"
+
+            if [ -n "${debug}" ]; then
+                echo "Parsing SUBPATHS entry: ${p}"
+                echo "  key: ${key}"
+                echo "  val: ${val}"
+            fi
+
+            SUBPATHS_COUNT=$((SUBPATHS_COUNT + 1))
+        done
+    fi
+}
+
+# Replace the given path with either entries from PROJRC or SUBPATHS
+# Arg 1: path
+apply_substitutions() {
+    # Repo name can have spaces in it, hence the use of ${*}
+    local path="${*}"
+
+    if [ ${PROJRC_COUNT} -ne 0 ]; then
+        for s in $(seq 0 $((${PROJRC_COUNT} - 1))); do
+            local pattern=${PROJRC_KEY[${s}]}
+            local replacement=${PROJRC_VAL[${s}]}
+
+            path=${path/${pattern}/${replacement}}
+        done
+    fi
+
+    if [ ${SUBPATHS_COUNT} -ne 0 ]; then
+        for s in $(seq 0 $((${SUBPATHS_COUNT} - 1))); do
+            local pattern=${SUBPATHS_KEY[${s}]}
+            local replacement=${SUBPATHS_VAL[${s}]}
+
+            path=${path/${pattern}/${replacement}}
+        done
+    fi
+
+    echo "${path}"
+}
+
+# git-remote-hg doesn't work with Mercurial projrc extension,
+# so use it manually.
+# We parse the projrc file in the assembly (on the server), to check
+# for any projrc substitutions.
+#
+# Arg 1: subproject (path and name)
+#
+# Return the new substitution name if found, and original subrepo name if not
+# (with the path stripped)
+hg_check_projrc_config() {
+    if [ ${#} -lt 1 ]; then
+        echo "Missing subrepos name"
+    fi
+
+    # Repo name can have spaces in it, hence the use of ${*}
+    local subrepo_orig="${*}"
+    local subrepo="${*}"
 
-    if [ -n ${subpaths} ]; then
-        sp_src=${subpaths//subpaths./}
-        sp_src=${sp_src//=*/}
-        sp_src=${sp_src//\\/} # Remove windows separator (LSI)
-        sp_dst=${subpaths//*=/}
+    # Quote spaces
+    subrepo=${subrepo// /\\\\ }
 
-        echo "sp_src = $sp_src"
-        echo "sp_dst = $sp_dst"
+    asm=$(cat .git/config | grep "hg::" | sed "s/.*url = hg::\(.*\)/\1/")
+
+    local baserepo=$(basename "${subrepo}")
+
+    if cat "${asm}/.hg/projrc" | grep -q "${baserepo}" ; then
+        projrc=$(cat "${asm}/.hg/projrc" | grep "${baserepo}" | sed "s/.*= \(.*\)/\1/")
+    else
+        # No substitution, return same name as original
+        projrc=$(basename "${subrepo_orig}")
     fi
+
+    echo "${projrc}"
 }
 
 # Map a revision to a branch name in HG subrepository
@@ -41,7 +174,7 @@ subrepo_find_branch() {
     local id="${2}"
     local rev="${3}"
 
-    pushd "${src}"
+    pushd "${src}" 1> /dev/null
 
     branch=$(hg log -r ${rev} | grep "branch:" | sed "s/branch:\ *//")
 
@@ -50,11 +183,15 @@ subrepo_find_branch() {
         branch=default
     fi
 
+    num=$(hg log --branch "${branch}" --template '{node}\n' | \
+        grep -n ${rev} | awk -F ':' '{print $1}')
+
     if [ -n "${debug}" ]; then
         echo "  branch: ${branch}"
+        echo "  num:    ${num}"
     fi
 
-    popd
+    popd 1> /dev/null
 }
 
 if [ "x${1}" = "x--help" ]; then
@@ -72,7 +209,15 @@ if [ ! -f .gitignore ]; then
     echo ".gitignore" > .gitignore
 fi
 
-hg_subpaths_config
+asm=$(cat .git/config | grep "hg::" | sed "s/.*url = hg::\(.*\)/\1/")
+hg_parse_projrc ${asm}
+
+hg_parse_subpaths
+
+HGSUB_TMP="/tmp/$(basename $0).hgsub-$$.tmp"
+
+# Create temporary copy to replace backslashes with slashes.
+cat .hgsub | sed 's/\\/\//g' > ${HGSUB_TMP}
 
 # Read lines from .hgsub
 while read sub; do
@@ -83,8 +228,12 @@ while read sub; do
         # Get subrepository URL
         src="${sub//*= /}"
 
-        # Replace using subpaths extension content
-        src=${src/${sp_src}/${sp_dst}}
+        # Replace using Mercurial subpaths substitutions (either projrc or from hgrc)
+        src=$(apply_substitutions ${src})
+
+        # Original name
+        repo=$(basename "${src}")
+        srcpath=$(dirname "${src}")
 
         # Get subrepository local alias or label
         dest="${sub// =*}"
@@ -96,11 +245,11 @@ while read sub; do
         rev=$(cat .hgsubstate | tr -d '\r' | grep "${id}" | sed "s/ .*//")
 
         if [ -n "${debug}" ]; then
-            echo "repo: ${src}"
-            echo "  id:     ${id}"
-            echo "  rev:    ${rev}"
-            echo "  src:    ${src}"
-            echo "  dest:   ${dest}"
+            echo "repo: ${repo}"
+            echo "  path:  ${srcpath}"
+            echo "  id:    ${id}"
+            echo "  local: ${dest}"
+            echo "  rev:   ${rev}"
         fi
 
         if [ ! -d "${dest}" ]; then
@@ -112,27 +261,41 @@ while read sub; do
             #   "BRANCH___-___NAME"
             branch="${branch// /___}"
 
+            if [ -n "${debug}" ]; then
+                echo "branch: ${branch}"
+            fi
+
             git clone "hg::${src}" "${dest}"
 
-            if [ "x${branch}" != "xdefault" ]; then
-                cd "${dest}"
-                git checkout "branches/${branch}"
+            cd "${dest}"
+
+            if [ -x ${HOME}/scripts/git-set-local-author.sh ]; then
+                # Make sure commits have correct author for LSI
+                ${HOME}/scripts/git-set-local-author.sh
+            fi
 
-                # This does not work: the SHA from hg and git
-                # are not the same...
-                #git reset --hard ${rev}
+            if [ "x${branch}" != "xdefault" ]; then
+                # Make tracking branch
+                git checkout -f "branches/${branch}"
 
-                cd ..
+                # Adjusting git tree to specific commit specified in
+                # .hgsubstate:
+                # The SHA from hg and git are not the same, therefore, we must
+                # find the commit sequence in hg and map this
+                # to a hash in git using the ${num} variable:
+                git_rev=$(git log --oneline | sed -n "${num}p" | awk '{print $1}')
+                git reset --hard ${git_rev}
             fi
 
+            cd ..
+
             if ! grep -q "${dest}" .gitignore ; then
                 # Ignore subrepo in top-level git repository
                 echo "${dest}" >> .gitignore
             fi
-        else
-            pushd "${dest}"
-            git pull
-            popd
         fi
     fi
-done < .hgsub
+done < ${HGSUB_TMP}
+
+rm ${HGSUB_TMP}
+