将Mercurial转换为SVN - 退出状态为256的svn

时间:2014-05-27 20:11:51

标签: svn ubuntu mercurial

命令运行:myself@ubuntu:/path/to/hg/repo hg convert -d svn . /home/myself/svn_output --debug --traceback

输出:

...
scanning: 366 revisions
sorting...
converting...
365 Clean solution based on Project Name containing DataAccess, Intranet
source: 916ac65351bb086dea665d2452838fbdb8d0c7da
converting: 0/366 revisions (0.00%)
getting files: file.vbproj 1/1078 (0.09%)
...
getting files: file.sln 1078/1078 (100.00%)
running: 'svn' 'delete' 'file.vb' < /dev/null
D         file.vb
running: 'svn' 'add' 'list,of,files' '--quiet' < /dev/null
running: 'svn' 'propdel' 'svn:executable' 'list,of,files' < /dev/null
run hg source post-conversion action
...
svn: Attempting to delete nonexistent property 'svn:executable'
run hg source post-conversion action
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 87, in _runcatch
    return _dispatch(req)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 684, in _dispatch
    cmdpats, cmdoptions)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 466, in runcommand
    ret = _runcommand(ui, options, cmd, d)
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 738, in _runcommand
    return checkargs()
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 692, in checkargs
    return cmdfunc()
  File "/usr/lib/python2.7/dist-packages/mercurial/dispatch.py", line 681, in <lambda>
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
  File "/usr/lib/python2.7/dist-packages/mercurial/util.py", line 458, in check
    return func(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/__init__.py", line 269, in convert
    return convcmd.convert(ui, src, dest, revmapfile, **opts)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/convcmd.py", line 445, in convert
    c.convert(sortmode)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/convcmd.py", line 361, in convert
    self.copy(c)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/convcmd.py", line 330, in copy
    source, self.map)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/subversion.py", line 1155, in putcommit
    self.xargs(self.delexec, 'propdel', 'svn:executable')
  File "/usr/lib/python2.7/dist-packages/hgext/convert/common.py", line 366, in xargs
    self.run0(cmd, *(list(args) + l), **kwargs)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/common.py", line 317, in run0
    self.checkexit(status, output)
  File "/usr/lib/python2.7/dist-packages/hgext/convert/common.py", line 313, in checkexit
    raise util.Abort('%s %s' % (self.command, msg))
Abort: svn exited with status 256
abort: svn exited with status 256

其他帖子似乎表明只需重新运行命令即可完成。但是,我还没有通过这一步并继续得到同样的错误。

1 个答案:

答案 0 :(得分:0)

我最终走向了另一个方向。基本上,我使用了一个bash脚本来完成这个技巧: http://qa-ex-consultant.blogspot.ca/2009/10/converting-mercurial-repo-to-subversion.html

记录保存来源:

#!/bin/bash

# DANGER: written as a once-off script, not suitable for naive consumption. Use at
# your own peril. It has been tested on one case only.
#
# Potential issues for reuse:
# * no sanity checks anywhere (don't call it with the wrong parameters)
# * no handling of branches
# * certain layout of the results of hg commands is assumed
# * all commits come from the user running the script
# * move operations probably won't appear in the history as such
# * we assume the SVN side doesn't change
#

HG_SOURCE=$1   # the source is a normal hg repository
SVN_TARGET=$2  # the target is a folder within a SVN working copy (e.g. /trunk)

export QUIET_FLAG= # -q for quiet, empty for verbose

echo Converting Mercurial repository at $HG_SOURCE into Subversion working copy at $SVN_TARGET

# Turn the SVN location into a mercurial one
pushd $SVN_TARGET
hg init .

# Get the revision counts (Overridable with START_REV, STOP_REV so you can restart if something bad happens)
pushd $HG_SOURCE
TIP_REV=`hg tip | head -1 | sed -e "s/[^ ]* *\([^:]*\)/\1/g"`
STOP_REV=$TIP_REV
START_REV=0
popd # out of $HG_SOURCE

# Pull all the changes from the mercurial repo, don't update though (helps with 
hg $QUIET_FLAG pull -r $TIP_REV $HG_SOURCE

for i in `seq $START_REV $STOP_REV`
do
    echo "Fetching Mercurial revision $i/$TIP_REV"
    hg $QUIET_FLAG update -C -r $i
    # Parse out the incoming log message
    HG_LOG_MESSAGE=`hg -R $HG_SOURCE -v log -r $i | grep -A10 ^description:$ | grep -v ^description:$ | head --lines=-2` 
    HG_LOG_CHANGESET=`hg -R $HG_SOURCE -v log -r $i | grep ^changeset: | head -1`
    HG_LOG_USER=`hg -R $HG_SOURCE -v log -r $i | grep ^user: | head -1`
    HG_LOG_DATE=`hg -R $HG_SOURCE -v log -r $i | grep ^date: | head -1`

    echo "- removing deleted files"
    svn status | grep '^!' | sed -e 's/^! *\(.*\)/\1/g' | while read fileToRemove
    do
        svn remove $QUIET_FLAG "$fileToRemove"
    done

    echo "- removing empty directories" # needed since Mercurial doesn't manage directories
    find . -name '.svn' -prune -o -type d -printf '%p+++' -exec ls -am {} \; | grep '., .., .svn$' | sed -e 's/^\(.*\)+++.*/\1/g' | while read dirToRemove
    do
        rm -rf "$dirToRemove" # remove first, otherwise working copy is broken for some reason only SVN knows
        svn remove $QUIET_FLAG "$dirToRemove"
    done

    echo "- adding files to SVN control"
    # 'svn add' recurses and snags .hg* files, we are pulling those out, so do our own recursion (slower but more stable)
    #   This is mostly important if you have sub-sites, as they each have a large .hg file in them
    while [ `svn status | grep '^\?' | grep -v '[ /].hg\(tags\|ignore\|sub\|substate\)\?\b' | wc -l` -gt 0 ]
    do
        svn status | grep '^\?' | grep -v '[ /].hg\(tags\|ignore\|sub\|substate\)\?\b' | sed -e 's/^\? *\(.*\)/\1/g' | while read fileToAdd
        do
            if [ -d "$fileToAdd" ]
            then
                # Mercurial seems to copy existing directories on moves or something like that -- we
                # definitely get some .svn subdirectories in newly created directories if the original
                # action was a move. New directories should never contain a .svn folder since that breaks
                # SVN 
                find "$fileToAdd" -type d -name ".svn" | while read accidentalSvnFolder
                do
                    rm -rf "$accidentalSvnFolder"
                done
            fi
            # Using --depth empty here, so we don't recurisivly add, we are taking care of that ourselves.
            svn add $QUIET_FLAG --depth empty "$fileToAdd"
        done
    done

    echo "- committing"
    # This section is here to specificly fix symlinks that get swapped between symlinks and real files
    #  But could be extended to catch any commit errors you can't know about until you try to submit
    # NOTE: This is a "done << EOF" style while loop so we can have a controlling variable to exit the loop
    #       otherwise NEED_COMMIT can't be modified in the body of the loop (bash pipe thingie)
    NEED_COMMIT=true
    while $NEED_COMMIT
    do
        NEED_COMMIT=false
        SVN_COMMIT_RESULT=`svn ci $QUIET_FLAG -m "$HG_LOG_CHANGESET
$HG_LOG_USER
$HG_LOG_DATE
$HG_LOG_MESSAGE" 2>&1`
        echo $SVN_COMMIT_RESULT

        while read needFixin;
        do
            if [ "$needFixin" != "" ]
            then
                svn pd svn:special $needFixin
                NEED_COMMIT=true
            fi
        done << EOF
$(echo "$SVN_COMMIT_RESULT" | grep "has unexpectedly changed special status" | sed -e 's/^svn: Entry \x27\(.*\)\x27 has unexpectedly .*$/\1/g')
EOF
    done
    echo "- done"
done

popd # out of $SVN_TARGET

我做的唯一更改是将HG_LOG_MESSAGE放在SVN提交消息中,而不是最后一次。