comparison utility_commands.py @ 304:ce676eff002b

First merge, totally untested.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Fri, 01 May 2009 10:28:59 +0200
parents 9f0738587f94
children 1d48d9a34c19
comparison
equal deleted inserted replaced
303:f423a8780832 304:ce676eff002b
1 import os 1 import os
2 2
3 import mercurial 3 from mercurial import util as hgutil
4 from mercurial import cmdutil
5 from mercurial import node
6 from mercurial import util as mutil
7 from hgext import rebase
8 4
9 import svnwrap 5 import svnwrap
6 import cmdutil
10 import util 7 import util
11 import hg_delta_editor 8 import hg_delta_editor
12 9
13 def print_wc_url(ui, repo, hg_repo_path, **opts): 10 def url(ui, repo, hg_repo_path, **opts):
14 """show the location (URL) of the Subversion repository 11 """show the location (URL) of the Subversion repository
15 """ 12 """
16 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, 13 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
17 ui_=ui) 14 ui_=ui)
18 ui.status(hge.url, '\n') 15 ui.status(hge.url, '\n')
19 print_wc_url = util.register_subcommand('url')(print_wc_url)
20 16
21 17
22 def find_wc_parent_rev(ui, repo, hge, svn_commit_hashes): 18 def genignore(ui, repo, hg_repo_path, force=False, **opts):
23 """Find the svn parent revision of the repo's dirstate.
24 """
25 workingctx = repo.parents()[0]
26 o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, workingctx.node())
27 if o_r:
28 workingctx = repo[o_r[-1]].parents()[0]
29 return workingctx
30
31
32 def generate_ignore(ui, repo, hg_repo_path, force=False, **opts):
33 """generate .hgignore from svn:ignore properties. 19 """generate .hgignore from svn:ignore properties.
34 """ 20 """
35 ignpath = os.path.join(hg_repo_path, '.hgignore') 21 ignpath = os.path.join(hg_repo_path, '.hgignore')
36 if not force and os.path.exists(ignpath): 22 if not force and os.path.exists(ignpath):
37 raise mutil.Abort('not overwriting existing .hgignore, try --force?') 23 raise hgutil.Abort('not overwriting existing .hgignore, try --force?')
38 ignorefile = open(ignpath, 'w') 24 ignorefile = open(ignpath, 'w')
39 ignorefile.write('.hgignore\nsyntax:glob\n') 25 ignorefile.write('.hgignore\nsyntax:glob\n')
40 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, 26 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
41 ui_=ui) 27 ui_=ui)
42 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), 28 svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
43 hge.revmap.iterkeys())) 29 hge.revmap.iterkeys()))
44 parent = find_wc_parent_rev(ui, repo, hge, svn_commit_hashes) 30 parent = cmdutil.parentrev(ui, repo, hge, svn_commit_hashes)
45 r, br = svn_commit_hashes[parent.node()] 31 r, br = svn_commit_hashes[parent.node()]
46 if br == None: 32 if br == None:
47 branchpath = 'trunk' 33 branchpath = 'trunk'
48 else: 34 else:
49 branchpath = 'branches/%s' % br 35 branchpath = 'branches/%s' % br
50 url = hge.url 36 url = hge.url
51 if url[-1] == '/': 37 if url[-1] == '/':
52 url = url[:-1] 38 url = url[:-1]
53 svn = svnwrap.SubversionRepo(url) 39 user, passwd = util.getuserpass(opts)
40 svn = svnwrap.SubversionRepo(url, user, passwd)
54 dirs = [''] + [d[0] for d in svn.list_files(branchpath, r) if d[1] == 'd'] 41 dirs = [''] + [d[0] for d in svn.list_files(branchpath, r) if d[1] == 'd']
55 for dir in dirs: 42 for dir in dirs:
56 props = svn.list_props('%s/%s/' % (branchpath,dir), r) 43 props = svn.list_props('%s/%s/' % (branchpath,dir), r)
57 if 'svn:ignore' in props: 44 if 'svn:ignore' in props:
58 lines = props['svn:ignore'].strip().split('\n') 45 lines = props['svn:ignore'].strip().split('\n')
59 for prop in lines: 46 for prop in lines:
60 if dir: 47 if dir:
61 ignorefile.write('%s/%s\n' % (dir, prop)) 48 ignorefile.write('%s/%s\n' % (dir, prop))
62 else: 49 else:
63 ignorefile.write('%s\n' % prop) 50 ignorefile.write('%s\n' % prop)
64 generate_ignore = util.register_subcommand('genignore')(generate_ignore)
65 51
66 52
67 def run_svn_info(ui, repo, hg_repo_path, **opts): 53 def info(ui, repo, hg_repo_path, **opts):
68 """show Subversion details similar to `svn info' 54 """show Subversion details similar to `svn info'
69 """ 55 """
70 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, 56 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
71 ui_=ui) 57 ui_=ui)
72 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), 58 svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
73 hge.revmap.iterkeys())) 59 hge.revmap.iterkeys()))
74 parent = find_wc_parent_rev(ui, repo, hge, svn_commit_hashes) 60 parent = cmdutil.parentrev(ui, repo, hge, svn_commit_hashes)
75 r, br = svn_commit_hashes[parent.node()] 61 pn = parent.node()
62 if pn not in svn_commit_hashes:
63 ui.status('Not a child of an svn revision.\n')
64 return 0
65 r, br = svn_commit_hashes[pn]
76 subdir = parent.extra()['convert_revision'][40:].split('@')[0] 66 subdir = parent.extra()['convert_revision'][40:].split('@')[0]
77 if br == None: 67 if br == None:
78 branchpath = '/trunk' 68 branchpath = '/trunk'
79 elif br.startswith('../'): 69 elif br.startswith('../'):
80 branchpath = '/%s' % br[3:] 70 branchpath = '/%s' % br[3:]
100 'uuid': open(hge.uuid_file).read(), 90 'uuid': open(hge.uuid_file).read(),
101 'url': url, 91 'url': url,
102 'author': author, 92 'author': author,
103 'revision': r, 93 'revision': r,
104 # TODO I'd like to format this to the user's local TZ if possible 94 # TODO I'd like to format this to the user's local TZ if possible
105 'date': mutil.datestr(parent.date(), 95 'date': hgutil.datestr(parent.date(),
106 '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') 96 '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
107 }) 97 })
108 run_svn_info = util.register_subcommand('info')(run_svn_info)
109 98
110 99
111 def print_parent_revision(ui, repo, hg_repo_path, **opts): 100 def listauthors(ui, args, authors=None, **opts):
112 """show Mercurial & Subversion parents of the working dir or revision 101 """list all authors in a Subversion repository
113 """ 102 """
114 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, 103 if not len(args):
115 ui_=ui) 104 ui.status('No repository specified.\n')
116 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), 105 return
117 hge.revmap.iterkeys())) 106 svn = svnwrap.SubversionRepo(util.normalize_url(args[0]))
118 ha = find_wc_parent_rev(ui, repo, hge, svn_commit_hashes) 107 author_set = set()
119 if ha.node() != node.nullid: 108 for rev in svn.revisions():
120 r, br = svn_commit_hashes[ha.node()] 109 author_set.add(str(rev.author)) # So None becomes 'None'
121 ui.status('Working copy parent revision is %s: r%s on %s\n' % 110 if authors:
122 (ha, r, br or 'trunk')) 111 authorfile = open(authors, 'w')
112 authorfile.write('%s=\n' % '=\n'.join(sorted(author_set)))
113 authorfile.close()
123 else: 114 else:
124 ui.status('Working copy seems to have no parent svn revision.\n') 115 ui.status('%s\n' % '\n'.join(sorted(author_set)))
125 return 0
126 print_parent_revision = util.register_subcommand('parent')(print_parent_revision)
127
128
129 def rebase_commits(ui, repo, hg_repo_path, extrafn=None, sourcerev=None, **opts):
130 """rebase current unpushed revisions onto the Subversion head
131
132 This moves a line of development from making its own head to the top of
133 Subversion development, linearizing the changes. In order to make sure you
134 rebase on top of the current top of Subversion work, you should probably run
135 'hg svn pull' before running this.
136 """
137 if extrafn is None:
138 def extrafn2(ctx, extra):
139 """defined here so we can add things easily.
140 """
141 extra['branch'] = ctx.branch()
142 extrafn = extrafn2
143 if sourcerev is None:
144 sourcerev = repo.parents()[0].node()
145 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
146 ui_=ui)
147 svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
148 hge.revmap.iterkeys()))
149 o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, sourcerev=sourcerev)
150 if not o_r:
151 ui.status('Nothing to rebase!\n')
152 return 0
153 if len(repo[sourcerev].children()):
154 ui.status('Refusing to rebase non-head commit like a coward\n')
155 return 0
156 parent_rev = repo[o_r[-1]].parents()[0]
157 target_rev = parent_rev
158 p_n = parent_rev.node()
159 exhausted_choices = False
160 while target_rev.children() and not exhausted_choices:
161 for c in target_rev.children():
162 exhausted_choices = True
163 n = c.node()
164 if (n in svn_commit_hashes and
165 svn_commit_hashes[n][1] == svn_commit_hashes[p_n][1]):
166 target_rev = c
167 exhausted_choices = False
168 break
169 if parent_rev == target_rev:
170 ui.status('Already up to date!\n')
171 return 0
172 # TODO this is really hacky, there must be a more direct way
173 return rebase.rebase(ui, repo, dest=node.hex(target_rev.node()),
174 base=node.hex(sourcerev),
175 extrafn=extrafn)
176 rebase_commits = util.register_subcommand('rebase')(rebase_commits)
177
178
179 def show_outgoing_to_svn(ui, repo, hg_repo_path, **opts):
180 """show changesets not found in the Subversion repository
181 """
182 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path,
183 ui_=ui)
184 svn_commit_hashes = dict(zip(hge.revmap.itervalues(),
185 hge.revmap.iterkeys()))
186 o_r = util.outgoing_revisions(ui, repo, hge, svn_commit_hashes, repo.parents()[0].node())
187 if not (o_r and len(o_r)):
188 ui.status('No outgoing changes found.\n')
189 return 0
190 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=False)
191 for node in reversed(o_r):
192 displayer.show(repo[node])
193 show_outgoing_to_svn = util.register_subcommand('outgoing')(show_outgoing_to_svn)
194 116
195 117
196 def version(ui, **opts): 118 def version(ui, **opts):
197 """Show current version of hg and hgsubversion. 119 """Show current version of hg and hgsubversion.
198 """ 120 """
199 ui.status('hg: %s\n' % mutil.version()) 121 ui.status('hg: %s\n' % hgutil.version())
200 ui.status('svn bindings: %s\n' % svnwrap.version()) 122 ui.status('svn bindings: %s\n' % svnwrap.version())
201 ui.status('hgsubversion: %s\n' % util.version(ui)) 123 ui.status('hgsubversion: %s\n' % util.version(ui))
202 version = util.register_subcommand('version')(version) 124
203 version = util.command_needs_no_url(version) 125
126 nourl = ['version', 'listauthors']
127 table = {
128 'url': url,
129 'genignore': genignore,
130 'info': info,
131 'listauthors': listauthors,
132 'version': version,
133 }