X-Git-Url: http://gitweb.hugovil.com/?a=blobdiff_plain;f=scripts%2Fgit-hg-sub-import;h=9d6ae493ea5c67affa4acdb1dc548238875f83e7;hb=cfa9caf6600913a0abe46bcc26a864e79bbec681;hp=d5d947fb3906d85cc7c60113c5d951ea27201391;hpb=bfb50df5b671e5de95fccd9ceaefe5b15ef04041;p=hvutilities.git diff --git a/scripts/git-hg-sub-import b/scripts/git-hg-sub-import index d5d947f..9d6ae49 100755 --- a/scripts/git-hg-sub-import +++ b/scripts/git-hg-sub-import @@ -1,13 +1,14 @@ #!/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() { @@ -15,6 +16,152 @@ 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="${*}" + + 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. @@ -27,7 +174,7 @@ subrepo_find_branch() { 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:\ *//") @@ -36,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 @@ -53,6 +204,21 @@ if [ ! -f .hgsub ]; 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) @@ -60,22 +226,30 @@ while read sub; do 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 @@ -87,17 +261,41 @@ while read sub; do # "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} +