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 |