Mercurial > hgsubversion
annotate push_cmd.py @ 7:79b0e059319d
Reorganized the testing infrastructure a bit so that svnwrap is really separate from the rest of the project. Also made it easier to add more tests in the future without making the directory full of annoying files.
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Fri, 03 Oct 2008 09:41:25 -0500 |
parents | 1a5bb173170b |
children | 9eb6bf2be1e7 |
rev | line source |
---|---|
0
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
1 from mercurial import util as merc_util |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
2 from mercurial import hg |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
3 from svn import core |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
4 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
5 import util |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
6 import hg_delta_editor |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
7 import svnwrap |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
8 import fetch_command |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
9 import utility_commands |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
10 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
11 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
12 @util.register_subcommand('push') |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
13 @util.register_subcommand('dcommit') # for git expats |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
14 def push_revisions_to_subversion(ui, repo, hg_repo_path, svn_url, **opts): |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
15 """Push revisions starting at a specified head back to Subversion. |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
16 """ |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
17 #assert False # safety while the command is partially implemented. |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
18 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
19 ui_=ui) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
20 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
21 hge.revmap.iterkeys())) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
22 # Strategy: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
23 # 1. Find all outgoing commits from this head |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
24 outgoing = utility_commands.outgoing_revisions(ui, repo, hge, |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
25 svn_commit_hashes) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
26 if not (outgoing and len(outgoing)): |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
27 ui.status('No revisions to push.') |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
28 return 0 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
29 if len(repo.parents()) != 1: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
30 ui.status('Cowardly refusing to push branch merge') |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
31 return 1 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
32 while outgoing: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
33 oldest = outgoing.pop(-1) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
34 old_ctx = repo[oldest] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
35 if len(old_ctx.parents()) != 1: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
36 ui.status('Found a branch merge, this needs discussion and ' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
37 'implementation.') |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
38 return 1 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
39 base_n = old_ctx.parents()[0].node() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
40 old_children = repo[base_n].children() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
41 # 2. Commit oldest revision that needs to be pushed |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
42 base_revision = svn_commit_hashes[old_ctx.parents()[0].node()][0] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
43 commit_from_rev(ui, repo, old_ctx, hge, svn_url, base_revision) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
44 # 3. Fetch revisions from svn |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
45 r = fetch_command.fetch_revisions(ui, svn_url, hg_repo_path) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
46 assert not r or r == 0 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
47 # 4. Find the new head of the target branch |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
48 repo = hg.repository(ui, hge.path) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
49 base_c = repo[base_n] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
50 replacement = [c for c in base_c.children() if c not in old_children |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
51 and c.branch() == old_ctx.branch()] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
52 assert len(replacement) == 1 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
53 replacement = replacement[0] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
54 # 5. Rebase all children of the currently-pushing rev to the new branch |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
55 heads = repo.heads(old_ctx.node()) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
56 for needs_transplant in heads: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
57 hg.clean(repo, needs_transplant) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
58 utility_commands.rebase_commits(ui, repo, hg_repo_path, **opts) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
59 repo = hg.repository(ui, hge.path) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
60 if needs_transplant in outgoing: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
61 hg.clean(repo, repo['tip'].node()) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
62 hge = hg_delta_editor.HgChangeReceiver(hg_repo_path, ui_=ui) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
63 svn_commit_hashes = dict(zip(hge.revmap.itervalues(), |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
64 hge.revmap.iterkeys())) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
65 outgoing = utility_commands.outgoing_revisions(ui, repo, hge, |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
66 svn_commit_hashes) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
67 return 0 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
68 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
69 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
70 def commit_from_rev(ui, repo, rev_ctx, hg_editor, svn_url, base_revision): |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
71 """Build and send a commit from Mercurial to Subversion. |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
72 """ |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
73 target_files = [] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
74 file_data = {} |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
75 for file in rev_ctx.files(): |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
76 parent = rev_ctx.parents()[0] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
77 new_data = base_data = '' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
78 action = '' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
79 if file in rev_ctx: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
80 new_data = rev_ctx.filectx(file).data() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
81 if file not in parent: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
82 target_files.append(file) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
83 action = 'add' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
84 # TODO check for mime-type autoprops here |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
85 # TODO check for directory adds here |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
86 else: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
87 target_files.append(file) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
88 base_data = parent.filectx(file).data() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
89 action = 'modify' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
90 else: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
91 target_files.append(file) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
92 base_data = parent.filectx(file).data() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
93 action = 'delete' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
94 file_data[file] = base_data, new_data, action |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
95 |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
96 # TODO check for directory deletes here |
6
1a5bb173170b
Fixes for win32 compatibility. Changes suggested by Shun-ichi GOTO, with some alterations by me.
Augie Fackler <durin42@gmail.com>
parents:
0
diff
changeset
|
97 svn = svnwrap.SubversionRepo(svn_url, username=merc_util.getuser()) |
0
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
98 parent_branch = rev_ctx.parents()[0].branch() |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
99 branch_path = 'trunk' |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
100 if parent_branch and parent_branch != 'default': |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
101 branch_path = 'branches/%s' % parent_branch |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
102 new_target_files = ['%s/%s' % (branch_path, f) for f in target_files] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
103 for tf, ntf in zip(target_files, new_target_files): |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
104 if tf in file_data: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
105 file_data[ntf] = file_data[tf] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
106 del file_data[tf] |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
107 try: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
108 svn.commit(new_target_files, rev_ctx.description(), file_data, |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
109 base_revision, set([])) |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
110 except core.SubversionException, e: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
111 if hasattr(e, 'apr_err') and e.apr_err == 160028: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
112 raise merc_util.Abort('Base text was out of date, maybe rebase?') |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
113 else: |
f2636cfed115
Initial import of hgsubversion into a public repository.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
114 raise |