allura
修訂 | 376f70a5beb1c86fadcf721ab079bc042bd876ab (tree) |
---|---|
時間 | 2011-10-06 02:14:56 |
作者 | Rick Copeland <rcopeland@geek...> |
Commiter | Rick Copeland |
[#2020] Add tests (and support) for SVN on new-style commits
Signed-off-by: Rick Copeland <rcopeland@geek.net>
@@ -7,12 +7,13 @@ from datetime import datetime | ||
7 | 7 | from collections import defaultdict |
8 | 8 | |
9 | 9 | from pylons import g |
10 | +import pymongo.errors | |
10 | 11 | |
11 | 12 | from ming import Field, Index, collection |
12 | 13 | from ming import schema as S |
13 | 14 | from ming.base import Object |
14 | 15 | from ming.utils import LazyProperty |
15 | -from ming.orm import mapper | |
16 | +from ming.orm import mapper, session | |
16 | 17 | |
17 | 18 | from allura.lib import utils |
18 | 19 | from allura.lib import helpers as h |
@@ -117,6 +118,20 @@ class RepoObject(object): | ||
117 | 118 | def object_id(self): |
118 | 119 | return self._id |
119 | 120 | |
121 | + @classmethod | |
122 | + def upsert(cls, id): | |
123 | + isnew = False | |
124 | + r = cls.query.get(_id=id) | |
125 | + if r is not None: return r, isnew | |
126 | + try: | |
127 | + r = cls(_id=id) | |
128 | + session(r).flush(r) | |
129 | + isnew = True | |
130 | + except pymongo.errors.DuplicateKeyError: # pragma no cover | |
131 | + session(r).expunge(r) | |
132 | + r = cls.query.get(_id=id) | |
133 | + return r, isnew | |
134 | + | |
120 | 135 | class Commit(RepoObject): |
121 | 136 | # Ephemeral attrs |
122 | 137 | repo=None |
@@ -137,12 +152,12 @@ class Commit(RepoObject): | ||
137 | 152 | @LazyProperty |
138 | 153 | def tree(self): |
139 | 154 | if self.tree_id is None: |
140 | - self.tree_id = self.repo.compute_tree(self) | |
155 | + self.tree_id = self.repo.compute_tree_new(self) | |
141 | 156 | if self.tree_id is None: |
142 | 157 | return None |
143 | 158 | t = Tree.query.get(_id=self.tree_id) |
144 | 159 | if t is None: |
145 | - self.tree_id = self.repo.compute_tree(self) | |
160 | + self.tree_id = self.repo.compute_tree_new(self) | |
146 | 161 | t = Tree.query.get(_id=self.tree_id) |
147 | 162 | if t is not None: t.set_context(self) |
148 | 163 | return t |
@@ -97,6 +97,10 @@ class RepositoryImplementation(object): | ||
97 | 97 | '''Used in hg and svn to compute a git-like-tree lazily''' |
98 | 98 | raise NotImplementedError, 'compute_tree' |
99 | 99 | |
100 | + def compute_tree_new(self, commit, path='/'): | |
101 | + '''Used in hg and svn to compute a git-like-tree lazily with the new models''' | |
102 | + raise NotImplementedError, 'compute_tree' | |
103 | + | |
100 | 104 | def open_blob(self, blob): # pragma no cover |
101 | 105 | '''Return a file-like object that contains the contents of the blob''' |
102 | 106 | raise NotImplementedError, 'open_blob' |
@@ -199,6 +203,8 @@ class Repository(Artifact): | ||
199 | 203 | return self._impl.url_for_commit(commit) |
200 | 204 | def compute_tree(self, commit, path='/'): |
201 | 205 | return self._impl.compute_tree(commit, path) |
206 | + def compute_tree_new(self, commit, path='/'): | |
207 | + return self._impl.compute_tree_new(commit, path) | |
202 | 208 | |
203 | 209 | def _log(self, rev, skip, max_count): |
204 | 210 | ci = self.commit(rev) |
@@ -310,6 +310,40 @@ class SVNImplementation(M.RepositoryImplementation): | ||
310 | 310 | session(tree).flush(tree) |
311 | 311 | return tree_id |
312 | 312 | |
313 | + def compute_tree_new(self, commit, tree_path='/'): | |
314 | + from allura.model import repo as RM | |
315 | + tree_path = tree_path[:-1] | |
316 | + tree_id = self._tree_oid(commit.object_id, tree_path) | |
317 | + tree, isnew = RM.Tree.upsert(tree_id) | |
318 | + if not isnew: return tree_id | |
319 | + log.debug('Computing tree for %s: %s', | |
320 | + self._revno(commit.object_id), tree_path) | |
321 | + rev = self._revision(commit.object_id) | |
322 | + try: | |
323 | + infos = self._svn.info2( | |
324 | + self._url + tree_path, | |
325 | + revision=rev, | |
326 | + depth=pysvn.depth.immediates) | |
327 | + except pysvn.ClientError: | |
328 | + log.exception('Error computing tree for %s: %s(%s)', | |
329 | + self._repo, commit, tree_path) | |
330 | + tree.delete() | |
331 | + return None | |
332 | + log.debug('Compute tree for %d paths', len(infos)) | |
333 | + for path, info in infos[1:]: | |
334 | + if info.kind == pysvn.node_kind.dir: | |
335 | + tree.tree_ids.append(Object( | |
336 | + id=self._tree_oid(commit.object_id, path), | |
337 | + name=path)) | |
338 | + elif info.kind == pysvn.node_kind.file: | |
339 | + tree.blob_ids.append(Object( | |
340 | + id=self._tree_oid(commit.object_id, path), | |
341 | + name=path)) | |
342 | + else: | |
343 | + assert False | |
344 | + session(tree).flush(tree) | |
345 | + return tree_id | |
346 | + | |
313 | 347 | def _tree_oid(self, commit_id, path): |
314 | 348 | data = 'tree\n%s\n%s' % (commit_id, h.really_unicode(path)) |
315 | 349 | return sha1(data.encode('utf-8')).hexdigest() |
@@ -51,12 +51,10 @@ class TestNewRepo(unittest.TestCase): | ||
51 | 51 | ci.context() |
52 | 52 | self.rev.tree.ls() |
53 | 53 | assert self.rev.tree.readme() == ( |
54 | - 'README', '<pre>This is readme\nAnother line\n</pre>') | |
54 | + 'README', '<pre>This is readme\nAnother Line\n</pre>') | |
55 | 55 | assert self.rev.tree.path() == '/' |
56 | 56 | assert self.rev.tree.url() == ( |
57 | - '/p/test/src/ci/' | |
58 | - '1c7eb55bbd66ff45906b4a25d4b403899e0ffff1/' | |
59 | - 'tree/') | |
57 | + '/p/test/src/5/tree/') | |
60 | 58 | self.rev.tree.by_name['README'] |
61 | 59 | assert self.rev.tree.is_blob('README') == True |
62 | 60 |