Mercurial > hgsubversion
comparison svncommands.py @ 256:7932d098cb5f
Refactor commands to wrap their hg equivalent adding a --svn flag where sane.
| author | Augie Fackler <durin42@gmail.com> |
|---|---|
| date | Fri, 10 Apr 2009 18:47:18 -0500 |
| parents | 246aaefb1cc0 |
| children | ffccf0080e54 |
comparison
equal
deleted
inserted
replaced
| 255:246aaefb1cc0 | 256:7932d098cb5f |
|---|---|
| 1 import os | 1 import os |
| 2 import cPickle as pickle | 2 import cPickle as pickle |
| 3 | 3 |
| 4 from mercurial import cmdutil as hgcmdutil | |
| 5 from mercurial import commands | |
| 4 from mercurial import hg | 6 from mercurial import hg |
| 5 from mercurial import node | 7 from mercurial import node |
| 6 from mercurial import patch | 8 from mercurial import patch |
| 7 from mercurial import util as hgutil | 9 from mercurial import util as hgutil |
| 8 | 10 |
| 15 import cmdutil | 17 import cmdutil |
| 16 import util | 18 import util |
| 17 import utility_commands | 19 import utility_commands |
| 18 | 20 |
| 19 | 21 |
| 20 def pull(ui, svn_url, hg_repo_path, skipto_rev=0, stupid=None, | 22 def clone(orig, ui, source, dest=None, **opts): |
| 21 tag_locations='tags', authors=None, filemap=None, **opts): | 23 '''clone Subversion repository to a local Mercurial repository. |
| 24 | |
| 25 If no destination directory name is specified, it defaults to the | |
| 26 basename of the source plus "-hg". | |
| 27 | |
| 28 You can specify multiple paths for the location of tags using comma | |
| 29 separated values. | |
| 30 ''' | |
| 31 svnurl = ui.expandpath(source) | |
| 32 if not cmdutil.issvnurl(svnurl): | |
| 33 orig(ui, repo, source=source, dest=dest, *args, **opts) | |
| 34 | |
| 35 if not dest: | |
| 36 dest = hg.defaultdest(source) + '-hg' | |
| 37 ui.status("Assuming destination %s\n" % dest) | |
| 38 | |
| 39 if os.path.exists(dest): | |
| 40 raise hgutil.Abort("destination '%s' already exists" % dest) | |
| 41 url = util.normalize_url(svnurl) | |
| 42 res = -1 | |
| 43 try: | |
| 44 try: | |
| 45 res = pull(None, ui, None, True, opts.pop('svn_stupid', False), | |
| 46 source=url, create_new_dest=dest, **opts) | |
| 47 except core.SubversionException, e: | |
| 48 if e.apr_err == core.SVN_ERR_RA_SERF_SSL_CERT_UNTRUSTED: | |
| 49 raise hgutil.Abort('It appears svn does not trust the ssl cert for this site.\n' | |
| 50 'Please try running svn ls on that url first.') | |
| 51 raise | |
| 52 finally: | |
| 53 if os.path.exists(dest): | |
| 54 repo = hg.repository(ui, dest) | |
| 55 fp = repo.opener("hgrc", "w", text=True) | |
| 56 fp.write("[paths]\n") | |
| 57 # percent needs to be escaped for ConfigParser | |
| 58 fp.write("default = %(url)s\nsvn = %(url)s\n" % {'url': svnurl.replace('%', '%%')}) | |
| 59 fp.close() | |
| 60 if res is None or res == 0: | |
| 61 commands.update(ui, repo, repo['tip'].node()) | |
| 62 | |
| 63 return res | |
| 64 | |
| 65 | |
| 66 def pull(orig, ui, repo, svn=None, svn_stupid=False, source="default", create_new_dest=False, | |
| 67 *args, **opts): | |
| 22 """pull new revisions from Subversion | 68 """pull new revisions from Subversion |
| 23 """ | 69 """ |
| 70 url = ui.expandpath(source) | |
| 71 if not (cmdutil.issvnurl(url) or svn or create_new_dest): | |
| 72 orig(ui, repo, source=source, *args, **opts) | |
| 73 svn_url = url | |
| 24 svn_url = util.normalize_url(svn_url) | 74 svn_url = util.normalize_url(svn_url) |
| 25 old_encoding = util.swap_out_encoding() | 75 old_encoding = util.swap_out_encoding() |
| 26 skipto_rev=int(skipto_rev) | 76 # TODO implement skipto support |
| 27 have_replay = not stupid | 77 skipto_rev = 0 |
| 78 have_replay = not svn_stupid | |
| 28 if have_replay and not callable( | 79 if have_replay and not callable( |
| 29 delta.svn_txdelta_apply(None, None, None)[0]): #pragma: no cover | 80 delta.svn_txdelta_apply(None, None, None)[0]): #pragma: no cover |
| 30 ui.status('You are using old Subversion SWIG bindings. Replay will not' | 81 ui.status('You are using old Subversion SWIG bindings. Replay will not' |
| 31 ' work until you upgrade to 1.5.0 or newer. Falling back to' | 82 ' work until you upgrade to 1.5.0 or newer. Falling back to' |
| 32 ' a slower method that may be buggier. Please upgrade, or' | 83 ' a slower method that may be buggier. Please upgrade, or' |
| 36 initializing_repo = False | 87 initializing_repo = False |
| 37 user = opts.get('username', hgutil.getuser()) | 88 user = opts.get('username', hgutil.getuser()) |
| 38 passwd = opts.get('password', '') | 89 passwd = opts.get('password', '') |
| 39 svn = svnwrap.SubversionRepo(svn_url, user, passwd) | 90 svn = svnwrap.SubversionRepo(svn_url, user, passwd) |
| 40 author_host = "@%s" % svn.uuid | 91 author_host = "@%s" % svn.uuid |
| 41 tag_locations = tag_locations.split(',') | 92 # TODO these should be configurable again, but I'm torn on how. |
| 42 hg_editor = hg_delta_editor.HgChangeReceiver(hg_repo_path, | 93 # Maybe this should be configured in .hg/hgrc for each repo? Seems vaguely reasonable. |
| 43 ui_=ui, | 94 tag_locations = ['tags', ] |
| 44 subdir=svn.subdir, | 95 authors = None |
| 45 author_host=author_host, | 96 filemap = None |
| 46 tag_locations=tag_locations, | 97 if repo: |
| 47 authors=authors, | 98 hg_editor = hg_delta_editor.HgChangeReceiver(repo=repo) |
| 48 filemap=filemap) | 99 else: |
| 100 hg_editor = hg_delta_editor.HgChangeReceiver(ui_=ui, | |
| 101 path=create_new_dest, | |
| 102 subdir=svn.subdir, | |
| 103 author_host=author_host, | |
| 104 tag_locations=tag_locations, | |
| 105 authors=authors, | |
| 106 filemap=filemap) | |
| 49 if os.path.exists(hg_editor.uuid_file): | 107 if os.path.exists(hg_editor.uuid_file): |
| 50 uuid = open(hg_editor.uuid_file).read() | 108 uuid = open(hg_editor.uuid_file).read() |
| 51 assert uuid == svn.uuid | 109 assert uuid == svn.uuid |
| 52 start = hg_editor.last_known_revision() | 110 start = hg_editor.last_known_revision() |
| 53 else: | 111 else: |
| 144 l1 = label+':' | 202 l1 = label+':' |
| 145 ui.status('%s%s\n' % (l1.ljust(13), | 203 ui.status('%s%s\n' % (l1.ljust(13), |
| 146 str(r.__getattribute__(attr)).strip(), )) | 204 str(r.__getattribute__(attr)).strip(), )) |
| 147 | 205 |
| 148 | 206 |
| 149 def push(ui, repo, hg_repo_path, svn_url, stupid=False, **opts): | 207 def push(orig, ui, repo, dest=None, **opts): |
| 150 """push revisions starting at a specified head back to Subversion. | 208 """push revisions starting at a specified head back to Subversion. |
| 151 """ | 209 """ |
| 210 svnurl = ui.expandpath(dest or 'default-push', dest or 'default') | |
| 211 if not cmdutil.issvnurl(svnurl): | |
| 212 orig(ui, repo, dest=dest, *args, **opts) | |
| 152 old_encoding = util.swap_out_encoding() | 213 old_encoding = util.swap_out_encoding() |
| 153 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, | 214 hge = hg_delta_editor.HgChangeReceiver(repo=repo) |
| 154 ui_=ui) | 215 assert svnurl == hge.url |
| 155 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), | 216 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), |
| 156 hge.revmap.iterkeys())) | 217 hge.revmap.iterkeys())) |
| 157 user = opts.get('username', hgutil.getuser()) | 218 user = opts.get('username', hgutil.getuser()) |
| 158 passwd = opts.get('password', '') | 219 passwd = opts.get('password', '') |
| 159 | 220 |
| 185 samebranchchildren = [c for c in repo[oldtip].children() if c.branch() == svnbranch | 246 samebranchchildren = [c for c in repo[oldtip].children() if c.branch() == svnbranch |
| 186 and c.node() in svn_commit_hashes] | 247 and c.node() in svn_commit_hashes] |
| 187 # 2. Commit oldest revision that needs to be pushed | 248 # 2. Commit oldest revision that needs to be pushed |
| 188 base_revision = svn_commit_hashes[base_n][0] | 249 base_revision = svn_commit_hashes[base_n][0] |
| 189 try: | 250 try: |
| 190 cmdutil.commit_from_rev(ui, repo, old_ctx, hge, svn_url, | 251 cmdutil.commit_from_rev(ui, repo, old_ctx, hge, svnurl, |
| 191 base_revision, user, passwd) | 252 base_revision, user, passwd) |
| 192 except cmdutil.NoFilesException: | 253 except cmdutil.NoFilesException: |
| 193 ui.warn("Could not push revision %s because it had no changes in svn.\n" % | 254 ui.warn("Could not push revision %s because it had no changes in svn.\n" % |
| 194 old_ctx) | 255 old_ctx) |
| 195 return 1 | 256 return 1 |
| 196 # 3. Fetch revisions from svn | 257 # 3. Fetch revisions from svn |
| 197 r = pull(ui, svn_url, hg_repo_path, stupid=stupid, | 258 r = pull(None, ui, repo, True, stupid=opts.get('svn_stupid', False), |
| 198 username=user, password=passwd) | 259 username=user, password=passwd) |
| 199 assert not r or r == 0 | 260 assert not r or r == 0 |
| 200 # 4. Find the new head of the target branch | 261 # 4. Find the new head of the target branch |
| 201 repo = hg.repository(ui, hge.path) | 262 repo = hg.repository(ui, hge.path) |
| 202 oldtipctx = repo[oldtip] | 263 oldtipctx = repo[oldtip] |
| 223 [child.node(), ] + outgoing[rebsrcindex+1:]) | 284 [child.node(), ] + outgoing[rebsrcindex+1:]) |
| 224 children = [c for c in child.children() if c.branch() == child.branch()] | 285 children = [c for c in child.children() if c.branch() == child.branch()] |
| 225 if children: | 286 if children: |
| 226 child = children[0] | 287 child = children[0] |
| 227 rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid))) | 288 rebasesrc = node.bin(child.extra().get('rebase_source', node.hex(node.nullid))) |
| 228 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, ui_=ui) | 289 hge = hg_delta_editor.HgChangeReceiver(hge.path, ui_=ui) |
| 229 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), hge.revmap.iterkeys())) | 290 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), hge.revmap.iterkeys())) |
| 230 util.swap_out_encoding(old_encoding) | 291 util.swap_out_encoding(old_encoding) |
| 231 return 0 | 292 return 0 |
| 232 | 293 |
| 233 | 294 |
| 234 def diff(ui, repo, hg_repo_path, **opts): | 295 def diff(orig, ui, repo, *args, **opts): |
| 235 """show a diff of the most recent revision against its parent from svn | 296 """show a diff of the most recent revision against its parent from svn |
| 236 """ | 297 """ |
| 237 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, | 298 if not opts.get('svn', False) or opts.get('change', None): |
| 238 ui_=ui) | 299 return orig(ui, repo, *args, **opts) |
| 300 svn_commit_hashes = {} | |
| 301 hge = hg_delta_editor.HgChangeReceiver(repo=repo) | |
| 239 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), | 302 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), |
| 240 hge.revmap.iterkeys())) | 303 hge.revmap.iterkeys())) |
| 241 parent = repo.parents()[0] | 304 if not opts.get('rev', None): |
| 242 o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, parent.node()) | 305 parent = repo.parents()[0] |
| 243 if o_r: | 306 o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, |
| 244 parent = repo[o_r[-1]].parents()[0] | 307 parent.node()) |
| 245 base_rev, _junk = svn_commit_hashes[parent.node()] | 308 if o_r: |
| 246 it = patch.diff(repo, parent.node(), None, | 309 parent = repo[o_r[-1]].parents()[0] |
| 310 opts['rev'] = ['%s:.' % node.hex(parent.node()), ] | |
| 311 node1, node2 = hgcmdutil.revpair(repo, opts['rev']) | |
| 312 baserev, _junk = svn_commit_hashes.get(node1, (-1, 'junk', )) | |
| 313 newrev, _junk = svn_commit_hashes.get(node2, (-1, 'junk', )) | |
| 314 it = patch.diff(repo, node1, node2, | |
| 247 opts=patch.diffopts(ui, opts={'git': True, | 315 opts=patch.diffopts(ui, opts={'git': True, |
| 248 'show_function': False, | 316 'show_function': False, |
| 249 'ignore_all_space': False, | 317 'ignore_all_space': False, |
| 250 'ignore_space_change': False, | 318 'ignore_space_change': False, |
| 251 'ignore_blank_lines': False, | 319 'ignore_blank_lines': False, |
| 252 'unified': True, | 320 'unified': True, |
| 253 'text': False, | 321 'text': False, |
| 254 })) | 322 })) |
| 255 ui.write(cmdutil.filterdiff(''.join(it), base_rev)) | 323 ui.write(cmdutil.filterdiff(''.join(it), baserev, newrev)) |
| 256 | 324 |
| 257 | 325 |
| 258 def rebuildmeta(ui, repo, hg_repo_path, args, **opts): | 326 def rebuildmeta(ui, repo, hg_repo_path, args, **opts): |
| 259 """rebuild hgsubversion metadata using values stored in revisions | 327 """rebuild hgsubversion metadata using values stored in revisions |
| 260 """ | 328 """ |
| 418 return 1 | 486 return 1 |
| 419 | 487 |
| 420 | 488 |
| 421 nourl = ['rebuildmeta'] + utility_commands.nourl | 489 nourl = ['rebuildmeta'] + utility_commands.nourl |
| 422 table = { | 490 table = { |
| 423 'pull': pull, | |
| 424 'push': push, | |
| 425 'dcommit': push, | |
| 426 'update': update, | 491 'update': update, |
| 427 'help': help, | 492 'help': help, |
| 428 'rebuildmeta': rebuildmeta, | 493 'rebuildmeta': rebuildmeta, |
| 429 'diff': diff, | |
| 430 'incoming': incoming, | 494 'incoming': incoming, |
| 431 } | 495 } |
| 432 | 496 |
| 433 table.update(utility_commands.table) | 497 table.update(utility_commands.table) |
| 434 | 498 |
