Mercurial > hgsubversion
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 } |