2308
by Jelmer Vernooij
Update copyright years. |
1 |
# Copyright (C) 2006-2009 Jelmer Vernooij <jelmer@samba.org>
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
2 |
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
2632
by Jelmer Vernooij
Change license back to GPLv2+. |
5 |
# the Free Software Foundation; either version 2 of the License, or
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
6 |
# (at your option) any later version.
|
7 |
||
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
||
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
16 |
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
17 |
"""Subversion server implementation."""
|
18 |
||
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
19 |
|
20 |
from bzrlib.plugins.svn import lazy_check_versions |
|
21 |
lazy_check_versions() |
|
22 |
||
2700
by Jelmer Vernooij
Reformat imports. |
23 |
import os |
24 |
import subvertpy |
|
25 |
from subvertpy import properties |
|
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
26 |
from subvertpy.ra_svn import ( |
27 |
SVN_PORT, |
|
28 |
SVNServer, |
|
29 |
TCPSVNServer, |
|
30 |
)
|
|
2700
by Jelmer Vernooij
Reformat imports. |
31 |
from subvertpy.server import ( |
32 |
ServerBackend, |
|
33 |
ServerRepositoryBackend, |
|
34 |
)
|
|
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
35 |
import sys |
2700
by Jelmer Vernooij
Reformat imports. |
36 |
import time |
37 |
||
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
38 |
from bzrlib import ( |
39 |
trace, |
|
40 |
urlutils, |
|
41 |
)
|
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
42 |
from bzrlib.branch import Branch |
1929.1.21
by Jelmer Vernooij
Get most of the tree content reporting working. |
43 |
from bzrlib.inventory import Inventory |
44 |
||
45 |
from bzrlib.plugins.svn.commit import dir_editor_send_changes |
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
46 |
|
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
47 |
|
1929.1.6
by Jelmer Vernooij
Support log -v. |
48 |
def determine_changed_paths(repository, branch_path, rev, revno): |
49 |
def fixpath(p): |
|
50 |
return "%s/%s" % (branch_path, p.encode("utf-8")) |
|
51 |
changes = {} |
|
52 |
changes[branch_path] = ("M", None, -1) # Always changes |
|
53 |
delta = repository.get_revision_delta(rev.revision_id) |
|
54 |
for (path, id, kind) in delta.added: |
|
55 |
changes[fixpath(path)] = ("A", None, -1) |
|
56 |
for (path, id, kind) in delta.removed: |
|
57 |
changes[fixpath(path)] = ("D", None, -1) |
|
58 |
for (oldpath, newpath, id, kind, text_modified, meta_modified) in delta.renamed: |
|
59 |
changes[fixpath(newpath)] = ("A", fixpath(oldpath), revno-1) |
|
60 |
changes[fixpath(oldpath)] = ("D", None, -1) |
|
61 |
for (path, id, kind, text_modified, meta_modified) in delta.modified: |
|
62 |
changes[fixpath(path)] = ("M", None, -1) |
|
63 |
return changes |
|
64 |
||
65 |
||
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
66 |
class RepositoryBackend(ServerRepositoryBackend): |
67 |
||
68 |
def __init__(self, branch): |
|
69 |
self.branch = branch |
|
70 |
||
71 |
def get_uuid(self): |
|
72 |
config = self.branch.get_config() |
|
73 |
uuid = config.get_user_option('svn_uuid') |
|
74 |
if uuid is None: |
|
75 |
import uuid |
|
76 |
uuid = uuid.uuid4() |
|
77 |
config.set_user_option('svn_uuid', uuid) |
|
78 |
return str(uuid) |
|
79 |
||
1929.1.4
by Jelmer Vernooij
Claim edit-pipeline capability, to make svn 1.5 happy. |
80 |
def get_latest_revnum(self): |
81 |
return self.branch.revno() |
|
82 |
||
1929.1.14
by Jelmer Vernooij
Return revision properties. |
83 |
def _get_revid(self, revnum): |
1936
by Jelmer Vernooij
Some work implementing stat() in the server code. |
84 |
"""Find the revision id and branch path a particular revnum refers to."""
|
1929.1.14
by Jelmer Vernooij
Return revision properties. |
85 |
return "/trunk", self.branch.get_rev_id(revnum) |
86 |
||
1929.1.6
by Jelmer Vernooij
Support log -v. |
87 |
def log(self, send_revision, target_path, start_rev, end_rev, report_changed_paths, |
1929.1.3
by Jelmer Vernooij
Override log for server. |
88 |
strict_node, limit): |
89 |
i = 0 |
|
90 |
revno = start_rev |
|
91 |
self.branch.repository.lock_read() |
|
92 |
try: |
|
93 |
# FIXME: check whether start_rev and end_rev actually exist
|
|
94 |
while revno != end_rev: |
|
95 |
#TODO: Honor target_path, strict_node, changed_paths
|
|
96 |
if end_rev > revno: |
|
97 |
revno+=1 |
|
98 |
else: |
|
99 |
revno-=1 |
|
100 |
if limit != 0 and i == limit: |
|
101 |
break
|
|
1929.1.6
by Jelmer Vernooij
Support log -v. |
102 |
if revno > 0: |
1929.1.14
by Jelmer Vernooij
Return revision properties. |
103 |
(path, revid) = self._get_revid(revno) |
104 |
rev = self.branch.repository.get_revision(revid) |
|
1929.1.6
by Jelmer Vernooij
Support log -v. |
105 |
if report_changed_paths: |
1929.1.14
by Jelmer Vernooij
Return revision properties. |
106 |
changes = determine_changed_paths(self.branch.repository, path, rev, revno) |
1929.1.6
by Jelmer Vernooij
Support log -v. |
107 |
else: |
108 |
changes = None |
|
109 |
send_revision(revno, |
|
110 |
rev.committer, time.strftime("%Y-%m-%dT%H:%M:%S.00000Z", time.gmtime(rev.timestamp)), |
|
111 |
rev.message, changed_paths=changes) |
|
1929.1.3
by Jelmer Vernooij
Override log for server. |
112 |
finally: |
113 |
self.branch.repository.unlock() |
|
1929.1.8
by Jelmer Vernooij
Implement check_path, make update abstract. |
114 |
|
1929.1.13
by Jelmer Vernooij
Support get-locations. |
115 |
def rev_proplist(self, revnum): |
1929.1.14
by Jelmer Vernooij
Return revision properties. |
116 |
path, revid = self._get_revid(revnum) |
117 |
rev = self.branch.repository.get_revision(revid) |
|
118 |
ret = { |
|
1961
by Jelmer Vernooij
Remove some more unused imports, fix formatting of imports. |
119 |
properties.PROP_REVISION_AUTHOR: rev.committer, |
120 |
properties.PROP_REVISION_DATE: time.strftime("%Y-%m-%dT%H:%M:%S.00000Z", time.gmtime(rev.timestamp)), |
|
121 |
properties.PROP_REVISION_LOG: rev.message |
|
1929.1.14
by Jelmer Vernooij
Return revision properties. |
122 |
}
|
123 |
return ret |
|
1929.1.13
by Jelmer Vernooij
Support get-locations. |
124 |
|
1929.1.8
by Jelmer Vernooij
Implement check_path, make update abstract. |
125 |
def update(self, editor, revnum, target_path, recurse=True): |
1929.1.17
by Jelmer Vernooij
Fix update. |
126 |
if revnum is None: |
127 |
revnum = self.get_latest_revnum() |
|
1929.1.21
by Jelmer Vernooij
Get most of the tree content reporting working. |
128 |
path, revid = self._get_revid(revnum) |
1944
by Jelmer Vernooij
More work getting checkout to work - a simple file diff works now. |
129 |
relpath = None # FIXME |
1929.1.8
by Jelmer Vernooij
Implement check_path, make update abstract. |
130 |
editor.set_target_revision(revnum) |
131 |
root = editor.open_root() |
|
1929.1.21
by Jelmer Vernooij
Get most of the tree content reporting working. |
132 |
old_inv = Inventory(None) |
133 |
self.branch.repository.lock_read() |
|
134 |
try: |
|
135 |
new_tree = self.branch.repository.revision_tree(revid) |
|
136 |
new_inv = new_tree.inventory |
|
137 |
modified_files = {} |
|
138 |
visit_dirs = set() |
|
139 |
for name, ie in new_inv.iter_entries(): |
|
140 |
if ie.kind == "directory": |
|
141 |
visit_dirs.add(ie.file_id) |
|
142 |
elif ie.kind == 'file': |
|
143 |
modified_files[ie.file_id] = new_tree.get_file_text(ie.file_id) |
|
144 |
elif ie.kind == 'symlink': |
|
145 |
modified_files[ie.file_id] = "link %s" % ie.symlink_target |
|
146 |
||
147 |
dir_editor_send_changes(old_inv, new_inv, "", new_inv.root.file_id, |
|
1944
by Jelmer Vernooij
More work getting checkout to work - a simple file diff works now. |
148 |
root, "svn://localhost/", revnum-1, relpath, |
1929.1.21
by Jelmer Vernooij
Get most of the tree content reporting working. |
149 |
modified_files, visit_dirs) |
150 |
root.close() |
|
151 |
editor.close() |
|
152 |
finally: |
|
153 |
self.branch.repository.unlock() |
|
1929.1.8
by Jelmer Vernooij
Implement check_path, make update abstract. |
154 |
|
155 |
def check_path(self, path, revnum): |
|
1961
by Jelmer Vernooij
Remove some more unused imports, fix formatting of imports. |
156 |
return subvertpy.NODE_DIR |
1929.1.13
by Jelmer Vernooij
Support get-locations. |
157 |
|
158 |
def get_locations(self, path, peg_revnum, revnums): |
|
159 |
if path.strip() in ("trunk", ""): |
|
160 |
return dict([(rev, path) for rev in revnums]) |
|
161 |
raise NotImplementedError |
|
1929.1.3
by Jelmer Vernooij
Override log for server. |
162 |
|
1929.1.15
by Jelmer Vernooij
Improve stat() implementation. |
163 |
def stat(self, path, revnum): |
1936
by Jelmer Vernooij
Some work implementing stat() in the server code. |
164 |
if revnum is None: |
165 |
revnum = self.get_latest_revnum() |
|
166 |
branch_path, revid = self._get_revid(revnum) |
|
167 |
inv = self.branch.repository.get_inventory(revid) |
|
1990
by Jelmer Vernooij
Fix svn-serve. |
168 |
id = inv.path2id(path[len(branch_path):].strip("/")) |
1936
by Jelmer Vernooij
Some work implementing stat() in the server code. |
169 |
if id is None: |
170 |
return None |
|
171 |
ie = inv[id] |
|
172 |
ret = { "name": urlutils.basename(path) } |
|
173 |
if ie.kind == "directory": |
|
1961
by Jelmer Vernooij
Remove some more unused imports, fix formatting of imports. |
174 |
ret["kind"] = subvertpy.NODE_DIR |
1990
by Jelmer Vernooij
Fix svn-serve. |
175 |
ret["size"] = 0 |
1936
by Jelmer Vernooij
Some work implementing stat() in the server code. |
176 |
else: |
3124
by Jelmer Vernooij
Fix some errors pointed out by pyflakes. |
177 |
ret["kind"] = subvertpy.NODE_FILE |
1990
by Jelmer Vernooij
Fix svn-serve. |
178 |
ret["size"] = ie.text_size |
1936
by Jelmer Vernooij
Some work implementing stat() in the server code. |
179 |
ret["has-props"] = True |
180 |
ret["created-rev"] = 0 # FIXME |
|
181 |
ret["created-date"] = "" # FIXME |
|
182 |
ret["last-author"] = "" # FIXME |
|
183 |
||
184 |
return ret |
|
1929.1.15
by Jelmer Vernooij
Improve stat() implementation. |
185 |
|
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
186 |
|
187 |
class BzrServerBackend(ServerBackend): |
|
188 |
||
1929.1.4
by Jelmer Vernooij
Claim edit-pipeline capability, to make svn 1.5 happy. |
189 |
def __init__(self, rootdir): |
190 |
self.rootdir = rootdir |
|
191 |
||
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
192 |
def open_repository(self, path): |
1929.1.4
by Jelmer Vernooij
Claim edit-pipeline capability, to make svn 1.5 happy. |
193 |
(branch, relpath) = Branch.open_containing(os.path.join(self.rootdir, path)) |
1929.1.2
by Jelmer Vernooij
Add experimental svn-serve subcommand. |
194 |
return RepositoryBackend(branch), relpath |
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
195 |
|
196 |
||
197 |
def serve_svn(transport, host=None, port=None, inet=False): |
|
198 |
trace.warning("server support in bzr-svn is experimental.") |
|
199 |
||
3019
by Jelmer Vernooij
Avoid using lstrip. |
200 |
if transport.base.startswith("readonly+"): |
201 |
url = transport.base[len("readonly+"):] |
|
3016
by Jelmer Vernooij
Fix svn-serve. |
202 |
path = urlutils.local_path_from_url(url) |
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
203 |
|
3016
by Jelmer Vernooij
Fix svn-serve. |
204 |
backend = BzrServerBackend(path) |
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
205 |
if inet: |
206 |
def send_fn(data): |
|
207 |
sys.stdout.write(data) |
|
208 |
sys.stdout.flush() |
|
3016
by Jelmer Vernooij
Fix svn-serve. |
209 |
server = SVNServer(backend, sys.stdin.read, send_fn) |
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
210 |
else: |
211 |
if port is None: |
|
212 |
port = SVN_PORT |
|
213 |
if host is None: |
|
214 |
host = '0.0.0.0' |
|
3016
by Jelmer Vernooij
Fix svn-serve. |
215 |
server = TCPSVNServer(backend, (host, port)) |
3015
by Jelmer Vernooij
merge bzr svn-serve back into bzr serve --svn. |
216 |
server.serve() |