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