2 from yap
import YapPlugin
, YapError
3 from yap
.util
import get_output
, takes_options
, run_command
, run_safely
, short_help
7 class SvnPlugin(YapPlugin
):
8 def __init__(self
, yap
):
11 def _get_root(self
, url
):
12 root
= get_output("svn info %s 2>/dev/null | gawk '/Repository Root:/{print $3}'" % url
)
14 raise YapError("Not an SVN repo: %s" % url
)
17 def _configure_repo(self
, url
):
18 root
= self
._get
_root
(url
)
19 os
.system("git config svn-remote.svn.url %s" % root
)
20 trunk
= url
.replace(root
, '').strip('/')
21 os
.system("git config svn-remote.svn.fetch %s:refs/remotes/svn/trunk"
23 branches
= trunk
.replace('trunk', 'branches')
24 os
.system("git config svn-remote.svn.branches %s/*:refs/remotes/svn/*"
26 tags
= trunk
.replace('trunk', 'tags')
27 os
.system("git config svn-remote.svn.tags %s/*:refs/tags/*" % tags
)
28 self
.yap
.cmd_repo("svn", url
)
29 os
.system("git config yap.svn.enabled 1")
31 def _clone_svn(self
, url
, directory
=None, **flags
):
34 directory
= url
.rsplit('/')[-1]
35 directory
= directory
.replace('.git', '')
40 raise YapError("Directory exists: %s" % directory
)
44 run_command("git config svn-remote.svn.noMetadata 1")
45 self
._configure
_repo
(url
)
46 os
.system("git svn fetch -r %s:HEAD" % flags
.get('-r', '1'))
48 def _push_svn(self
, branch
, **flags
):
50 raise YapError("Deleting svn branches not supported")
51 print "Verifying branch is up-to-date"
52 run_safely("git svn fetch svn")
54 branch
= branch
.replace('refs/heads/', '')
55 rev
= get_output("git rev-parse --verify refs/remotes/svn/%s" % branch
)
57 # Create the branch if requested
60 raise YapError("No matching branch on the repo. Use -c to create a new branch there.")
61 src
= get_output("git svn info | gawk '/URL:/{print $2}'")[0]
62 brev
= get_output("git svn info | gawk '/Revision:/{print $2}'")[0]
63 root
= get_output("git config svn-remote.svn.url")[0]
64 branch_path
= get_output("git config svn-remote.svn.branches")[0].split(':')[0]
65 branch_path
= branch_path
.rstrip('/*')
66 dst
= '/'.join((root
, branch_path
, branch
))
68 # Create the branch in svn
69 run_safely("svn cp -r%s %s %s -m 'create branch %s'"
70 % (brev
, src
, dst
, branch
))
71 run_safely("git svn fetch svn")
72 rev
= get_output("git rev-parse refs/remotes/svn/%s 2>/dev/null" % branch
)
73 base
= get_output("git svn find-rev r%s" % brev
)
75 # Apply our commits to the new branch
77 fd
, tmpfile
= tempfile
.mkstemp("yap")
80 os
.system("git format-patch -k --stdout '%s' > %s"
82 start
= get_output("git rev-parse HEAD")
83 self
.yap
.cmd_point("refs/remotes/svn/%s"
84 % branch
, **{'-f': True})
86 stat
= os
.stat(tmpfile
)
89 rc
= run_command("git am -3 %s" % tmpfile
)
91 self
.yap
.cmd_point(start
[0], **{'-f': True})
92 raise YapError("Failed to port changes to new svn branch")
96 base
= get_output("git merge-base HEAD %s" % rev
[0])
98 raise YapError("Branch not up-to-date. Update first.")
99 current
= get_output("git symbolic-ref HEAD")
101 raise YapError("Not on a branch!")
102 current
= current
[0].replace('refs/heads/', '')
103 self
.yap
._confirm
_push
(current
, branch
, "svn")
104 if run_command("git update-index --refresh"):
105 raise YapError("Can't push with uncommitted changes")
107 master
= get_output("git rev-parse --verify refs/heads/master 2>/dev/null")
108 os
.system("git svn dcommit")
109 run_safely("git svn rebase")
111 master
= get_output("git rev-parse --verify refs/heads/master 2>/dev/null")
113 run_safely("git update-ref -d refs/heads/master %s" % master
[0])
116 enabled
= get_output("git config yap.svn.enabled")
119 # Ensure users don't accidentally kill our "svn" repo
120 def pre_repo(self
, *args
, **flags
):
121 if not self
._enabled
():
123 if '-d' in flags
and args
and args
[0] == "svn":
124 raise YapError("Refusing to delete special svn repository")
127 def cmd_clone(self
, *args
, **flags
):
128 if args
and not run_command("svn info %s" % args
[0]):
129 self
._clone
_svn
(*args
, **flags
)
131 self
.yap
._call
_base
("cmd_commit", *args
, **flags
)
133 def cmd_fetch(self
, *args
, **flags
):
135 if args
and args
[0] == 'svn':
136 os
.system("git svn fetch svn")
139 current
= get_output("git symbolic-ref HEAD")
141 raise YapError("Not on a branch!")
143 current
= current
[0].replace('refs/heads/', '')
144 remote
, merge
= self
.yap
._get
_tracking
(current
)
146 os
.system("git svn fetch svn")
148 self
.yap
._call
_base
("cmd_fetch", *args
, **flags
)
150 def cmd_push(self
, *args
, **flags
):
152 if args
and args
[0] == 'svn':
154 raise YapError("Need a branch name")
155 self
._push
_svn
(args
[1], **flags
)
158 current
= get_output("git symbolic-ref HEAD")
160 raise YapError("Not on a branch!")
162 current
= current
[0].replace('refs/heads/', '')
163 remote
, merge
= self
.yap
._get
_tracking
(current
)
165 self
._push
_svn
(merge
, **flags
)
168 self
.yap
._call
_base
("cmd_push", *args
, **flags
)
170 @short_help("change options for the svn plugin")
171 def cmd_svn(self
, subcmd
):
174 if subcmd
not in ["enable"]:
177 if "svn" in [x
[0] for x
in self
.yap
._list
_remotes
()]:
178 raise YapError("A remote named 'svn' already exists")
181 if not run_command("git config svn-remote.svn.branches"):
182 raise YapError("Cannot currently enable in a repository with svn branches")
184 url
= get_output("git config svn-remote.svn.url")
186 raise YapError("Not a git-svn repository?")
187 fetch
= get_output("git config svn-remote.svn.fetch")
189 lhs
, rhs
= fetch
[0].split(':')
192 rev
= get_output("git rev-parse %s" % rhs
)
194 run_safely("git update-ref refs/remotes/svn/trunk %s" % rev
[0])
196 url
= '/'.join((url
[0], lhs
))
197 self
._configure
_repo
(url
)
198 run_safely("git update-ref -d %s %s" % (rhs
, rev
[0]))