#!/bin/bash
set -o errexit
-# Uncomment to have verboswe debug output
-#debug=1
-
# for use with git-remote-hg:
# http://felipec.wordpress.com/2012/11/13/git-remote-hg-bzr-2/
-LSI_SRV=/mnt/server/research/Projects/HG_Repo
+# Uncomment to have verbose debug output
+#debug=1
+
+PROJRC_COUNT=0
+SUBPATHS_COUNT=0
print_usage()
{
echo "Usage: $(basename $0) [OPTIONS...]"
}
+# 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_orig="${*}"
+ local repo="${*}"
+
+ # Quote spaces
+ repo=${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="${*}"
+
+ # Quote spaces
+ subrepo=${subrepo// /\\\\ }
+
+ 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
# Use hg log (in original repo) to get branch name corresponding to that
# revision.
local id="${2}"
local rev="${3}"
- pushd "${LSI_SRV}/${src}"
+ pushd "${src}" 1> /dev/null
branch=$(hg log -r ${rev} | grep "branch:" | sed "s/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
exit 1
fi
+if [ ! -f .gitignore ]; then
+ # We do not want to track .gitignore itself
+ echo ".gitignore" > .gitignore
+fi
+
+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
# Remove CR (DOS)
if [ "${sub}" != "" ]; then
# Get subrepository URL
- src="${sub//*\/HG_REPO/}"
+ src="${sub//*= /}"
+
+ # 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// =*}"
# Get project ID (example: S0289)
- id=$(echo ${sub} | sed "s/.*HG_REPO\(S[0-9][0-9][0-9][0-9]\).*/\1/")
+ id=$(echo ${sub} | sed "s/.*\(S[0-9][0-9][0-9][0-9]\).*/\1/")
# Get revision of subrepository (remove CR from .hgsubstate)
rev=$(cat .hgsubstate | tr -d '\r' | grep "${id}" | sed "s/ .*//")
if [ -n "${debug}" ]; then
- echo "repo: ${src}"
- echo " id: ${id}"
- echo " rev: ${rev}"
- echo " dest: ${dest}"
+ echo "repo: ${repo}"
+ echo " path: ${srcpath}"
+ echo " id: ${id}"
+ echo " local: ${dest}"
+ echo " rev: ${rev}"
fi
if [ ! -d "${dest}" ]; then
# "BRANCH___-___NAME"
branch="${branch// /___}"
- git clone "hg::${LSI_SRV}/${src}" "${dest}"
+ if [ -n "${debug}" ]; then
+ echo "branch: ${branch}"
+ fi
+
+ git clone "hg::${src}" "${dest}"
+
+ 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
if [ "x${branch}" != "xdefault" ]; then
- cd "${dest}"
- git checkout "branches/${branch}"
- cd ..
+ # Make tracking branch
+ git checkout -f "branches/${branch}"
+
+ # 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}
+