# 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}]}
- if [ -n ${subpaths} ]; then
- sp_src=${subpaths//subpaths./}
- sp_src=${sp_src//=*/}
- sp_src=${sp_src//\\/} # Remove windows separator (LSI)
- sp_dst=${subpaths//*=/}
+ 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}]}
- echo "sp_src = $sp_src"
- echo "sp_dst = $sp_dst"
+ path=${path/${pattern}/${replacement}}
+ done
fi
+
+ echo "${path}"
}
# Map a revision to a branch name in HG subrepository
local id="${2}"
local rev="${3}"
- pushd "${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
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
# 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// =*}"
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
# "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}"
- # This does not work: the SHA from hg and git
- # are not the same...
- #git reset --hard ${rev}
+ 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
- cd ..
+ if [ "x${branch}" != "xdefault" ]; then
+ # 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}
+