|
a/Allura/allura/model/repo.py |
|
b/Allura/allura/model/repo.py |
|
... |
|
... |
8 |
|
8 |
|
9 |
from pylons import g
|
9 |
from pylons import g
|
10 |
|
10 |
|
11 |
from ming import Field, Index, collection
|
11 |
from ming import Field, Index, collection
|
12 |
from ming import schema as S
|
12 |
from ming import schema as S
|
|
|
13 |
from ming.base import Object
|
13 |
from ming.utils import LazyProperty
|
14 |
from ming.utils import LazyProperty
|
14 |
from ming.orm import mapper
|
15 |
from ming.orm import mapper
|
15 |
|
16 |
|
16 |
from allura.lib import utils
|
17 |
from allura.lib import utils
|
17 |
from allura.lib import helpers as h
|
18 |
from allura.lib import helpers as h
|
|
... |
|
... |
20 |
from .session import main_doc_session, project_doc_session
|
21 |
from .session import main_doc_session, project_doc_session
|
21 |
from .session import repository_orm_session
|
22 |
from .session import repository_orm_session
|
22 |
|
23 |
|
23 |
log = logging.getLogger(__name__)
|
24 |
log = logging.getLogger(__name__)
|
24 |
|
25 |
|
|
|
26 |
# Some schema types
|
25 |
SUser = dict(name=str, email=str, date=datetime)
|
27 |
SUser = dict(name=str, email=str, date=datetime)
|
26 |
SObjType=S.OneOf('blob', 'tree', 'submodule')
|
28 |
SObjType=S.OneOf('blob', 'tree', 'submodule')
|
|
|
29 |
|
|
|
30 |
# Used for when we're going to batch queries using $in
|
27 |
QSIZE = 100
|
31 |
QSIZE = 100
|
28 |
README_RE = re.compile('^README(\.[^.]*)?$', re.IGNORECASE)
|
32 |
README_RE = re.compile('^README(\.[^.]*)?$', re.IGNORECASE)
|
29 |
|
33 |
|
30 |
# Basic commit information
|
34 |
# Basic commit information
|
31 |
CommitDoc = collection(
|
35 |
CommitDoc = collection(
|
|
... |
|
... |
86 |
Field('commit_ids', [str], index=True),
|
90 |
Field('commit_ids', [str], index=True),
|
87 |
Field('commit_times', [datetime]))
|
91 |
Field('commit_times', [datetime]))
|
88 |
|
92 |
|
89 |
class RepoObject(object):
|
93 |
class RepoObject(object):
|
90 |
|
94 |
|
91 |
def __repr__(self):
|
95 |
def __repr__(self): # pragma no cover
|
92 |
return '<%s %s>' % (
|
96 |
return '<%s %s>' % (
|
93 |
self.__class__.__name__, self._id)
|
97 |
self.__class__.__name__, self._id)
|
94 |
|
98 |
|
95 |
def primary(self):
|
99 |
def primary(self):
|
96 |
return self
|
100 |
return self
|
|
... |
|
... |
103 |
self.__class__.__module__,
|
107 |
self.__class__.__module__,
|
104 |
self.__class__.__name__,
|
108 |
self.__class__.__name__,
|
105 |
self._id)
|
109 |
self._id)
|
106 |
return id.replace('.', '/')
|
110 |
return id.replace('.', '/')
|
107 |
|
111 |
|
|
|
112 |
@LazyProperty
|
|
|
113 |
def legacy(self):
|
|
|
114 |
return Object(object_id=self._id)
|
|
|
115 |
|
108 |
class Commit(RepoObject):
|
116 |
class Commit(RepoObject):
|
109 |
# Ephemeral attrs
|
117 |
# Ephemeral attrs
|
110 |
repo=None
|
118 |
repo=None
|
|
|
119 |
|
|
|
120 |
def set_context(self, repo):
|
|
|
121 |
self.repo = repo
|
111 |
|
122 |
|
112 |
@LazyProperty
|
123 |
@LazyProperty
|
113 |
def author_url(self):
|
124 |
def author_url(self):
|
114 |
u = User.by_email_address(self.authored.email)
|
125 |
u = User.by_email_address(self.authored.email)
|
115 |
if u: return u.url()
|
126 |
if u: return u.url()
|
|
... |
|
... |
123 |
def tree(self):
|
134 |
def tree(self):
|
124 |
if self.tree_id is None:
|
135 |
if self.tree_id is None:
|
125 |
self.tree_id = self.repo.compute_tree(self)
|
136 |
self.tree_id = self.repo.compute_tree(self)
|
126 |
if self.tree_id is None:
|
137 |
if self.tree_id is None:
|
127 |
return None
|
138 |
return None
|
128 |
t = Tree.query.get(object_id=self.tree_id)
|
139 |
t = Tree.query.get(_id=self.tree_id)
|
129 |
if t is None:
|
140 |
if t is None:
|
130 |
self.tree_id = self.repo.compute_tree(self)
|
141 |
self.tree_id = self.repo.compute_tree(self)
|
131 |
t = Tree.query.get(object_id=self.tree_id)
|
142 |
t = Tree.query.get(_id=self.tree_id)
|
132 |
if t is not None: t.set_context(self)
|
143 |
if t is not None: t.set_context(self)
|
133 |
return t
|
144 |
return t
|
134 |
|
145 |
|
135 |
@LazyProperty
|
146 |
@LazyProperty
|
136 |
def summary(self):
|
147 |
def summary(self):
|
137 |
message = h.really_unicode(self.message)
|
148 |
message = h.really_unicode(self.message)
|
138 |
first_line = message.split('\n')[0]
|
149 |
first_line = message.split('\n')[0]
|
139 |
return h.text.truncate(first_line, 50)
|
150 |
return h.text.truncate(first_line, 50)
|
140 |
|
151 |
|
141 |
def get_path(self, path):
|
|
|
142 |
'''Return the blob on the given path'''
|
|
|
143 |
if path.startswith('/'): path = path[1:]
|
|
|
144 |
path_parts = path.split('/')
|
|
|
145 |
return self.tree.get_blob(path_parts[-1], path_parts[:-1])
|
|
|
146 |
|
|
|
147 |
def shorthand_id(self):
|
152 |
def shorthand_id(self):
|
148 |
return self.repo.shorthand_for_commit(self)
|
153 |
return self.repo.shorthand_for_commit(self._id)
|
149 |
|
154 |
|
150 |
@LazyProperty
|
155 |
@LazyProperty
|
151 |
def symbolic_ids(self):
|
156 |
def symbolic_ids(self):
|
152 |
return self.repo.symbolics_for_commit(self)
|
157 |
return self.repo.symbolics_for_commit(self.legacy)
|
153 |
|
158 |
|
154 |
def url(self):
|
159 |
def url(self):
|
155 |
return self.repo.url_for_commit(self)
|
160 |
return self.repo.url_for_commit(self.legacy)
|
156 |
|
161 |
|
157 |
def log_iter(self, skip, count):
|
162 |
def log_iter(self, skip, count):
|
158 |
for oids in utils.chunked_iter(commitlog(self._id), QSIZE):
|
163 |
for oids in utils.chunked_iter(commitlog(self._id), QSIZE):
|
159 |
oids = list(oids)
|
164 |
oids = list(oids)
|
160 |
commits = dict(
|
165 |
commits = dict(
|
161 |
(ci._id, ci) for ci in self.query.find(dict(
|
166 |
(ci._id, ci) for ci in self.query.find(dict(
|
162 |
_id={'$in': oids})))
|
167 |
_id={'$in': oids})))
|
163 |
for oid in oids:
|
168 |
for oid in oids:
|
|
|
169 |
if skip:
|
|
|
170 |
skip -= 1
|
|
|
171 |
continue
|
|
|
172 |
if count:
|
|
|
173 |
count -= 1
|
164 |
ci = commits[oid]
|
174 |
ci = commits[oid]
|
165 |
ci.set_context(self.repo)
|
175 |
ci.set_context(self.repo)
|
166 |
yield ci
|
176 |
yield ci
|
|
|
177 |
else:
|
|
|
178 |
break
|
167 |
|
179 |
|
168 |
def log(self, skip, count):
|
180 |
def log(self, skip, count):
|
169 |
return list(self.log_iter(skip, count))
|
181 |
return list(self.log_iter(skip, count))
|
170 |
|
182 |
|
171 |
def count_revisions(self):
|
183 |
def count_revisions(self):
|
172 |
result = 0
|
184 |
result = 0
|
173 |
for oid in commitlog(self): result += 1
|
185 |
for oid in commitlog(self._id): result += 1
|
174 |
return result
|
186 |
return result
|
175 |
|
187 |
|
176 |
def context(self):
|
188 |
def context(self):
|
177 |
result = dict(prev=None, next=None)
|
189 |
result = dict(prev=None, next=None)
|
178 |
if self.parent_ids:
|
190 |
if self.parent_ids:
|
|
... |
|
... |
215 |
name = None
|
227 |
name = None
|
216 |
text = ''
|
228 |
text = ''
|
217 |
for x in self.blob_ids:
|
229 |
for x in self.blob_ids:
|
218 |
if README_RE.match(x.name):
|
230 |
if README_RE.match(x.name):
|
219 |
name = x.name
|
231 |
name = x.name
|
|
|
232 |
text = self.repo.open_blob(Object(object_id=x.id)).read()
|
220 |
text = h.really_unicode(self.repo.blob_text(x.id))
|
233 |
text = h.really_unicode(text)
|
221 |
break
|
234 |
break
|
222 |
if text == '':
|
235 |
if text == '':
|
223 |
text = '<p><em>Empty File</em></p>'
|
236 |
text = '<p><em>Empty File</em></p>'
|
224 |
else:
|
237 |
else:
|
225 |
renderer = g.pypeline_markup.renderer(name)
|
238 |
renderer = g.pypeline_markup.renderer(name)
|
|
... |
|
... |
229 |
text = '<pre>%s</pre>' % text
|
242 |
text = '<pre>%s</pre>' % text
|
230 |
return (name, text)
|
243 |
return (name, text)
|
231 |
|
244 |
|
232 |
def ls(self):
|
245 |
def ls(self):
|
233 |
# Load last commit info
|
246 |
# Load last commit info
|
234 |
oids = [ x.id for x in chain(self.tree_ids, self.object_ids, self.other_ids) ]
|
247 |
oids = [ x.id for x in chain(self.tree_ids, self.blob_ids, self.other_ids) ]
|
235 |
lc_index = dict(
|
248 |
lc_index = dict(
|
236 |
(lc.object_id, lc.commit)
|
249 |
(lc.object_id, lc.commit_info)
|
237 |
for lc in LastCommitDoc.m.find(dict(
|
250 |
for lc in LastCommitDoc.m.find(dict(
|
238 |
repo_id=self.repo._id,
|
251 |
repo_id=self.repo._id,
|
239 |
object_id={'$in': oids})))
|
252 |
object_id={'$in': oids})))
|
240 |
results = []
|
253 |
results = []
|
241 |
def _get_last_commit(oid):
|
254 |
def _get_last_commit(oid):
|
|
... |
|
... |
291 |
(x.name, dict(x, type='blob'))
|
304 |
(x.name, dict(x, type='blob'))
|
292 |
for x in self.blob_ids)
|
305 |
for x in self.blob_ids)
|
293 |
return d
|
306 |
return d
|
294 |
|
307 |
|
295 |
def is_blob(self, name):
|
308 |
def is_blob(self, name):
|
296 |
return self.by_name[name].type == 'blob'
|
309 |
return self.by_name[name]['type'] == 'blob'
|
297 |
|
310 |
|
298 |
mapper(Commit, CommitDoc, repository_orm_session)
|
311 |
mapper(Commit, CommitDoc, repository_orm_session)
|
299 |
mapper(Tree, TreeDoc, repository_orm_session)
|
312 |
mapper(Tree, TreeDoc, repository_orm_session)
|
300 |
|
313 |
|
301 |
def commitlog(commit_id, skip=0, limit=sys.maxint):
|
314 |
def commitlog(commit_id, skip=0, limit=sys.maxint):
|