|
a/Allura/allura/model/repo.py |
|
b/Allura/allura/model/repo.py |
|
... |
|
... |
34 |
QSIZE = 100
|
34 |
QSIZE = 100
|
35 |
README_RE = re.compile('^README(\.[^.]*)?$', re.IGNORECASE)
|
35 |
README_RE = re.compile('^README(\.[^.]*)?$', re.IGNORECASE)
|
36 |
VIEWABLE_EXTENSIONS = ['.php','.py','.js','.java','.html','.htm','.yaml','.sh',
|
36 |
VIEWABLE_EXTENSIONS = ['.php','.py','.js','.java','.html','.htm','.yaml','.sh',
|
37 |
'.rb','.phtml','.txt','.bat','.ps1','.xhtml','.css','.cfm','.jsp','.jspx',
|
37 |
'.rb','.phtml','.txt','.bat','.ps1','.xhtml','.css','.cfm','.jsp','.jspx',
|
38 |
'.pl','.php4','.php3','.rhtml','.svg','.markdown','.json','.ini','.tcl','.vbs','.xsl']
|
38 |
'.pl','.php4','.php3','.rhtml','.svg','.markdown','.json','.ini','.tcl','.vbs','.xsl']
|
|
|
39 |
|
|
|
40 |
DIFF_SIMILARITY_THRESHOLD = .5 # used for determining file renames
|
39 |
|
41 |
|
40 |
# Basic commit information
|
42 |
# Basic commit information
|
41 |
# One of these for each commit in the physical repo on disk. The _id is the
|
43 |
# One of these for each commit in the physical repo on disk. The _id is the
|
42 |
# hexsha of the commit (for Git and Hg).
|
44 |
# hexsha of the commit (for Git and Hg).
|
43 |
CommitDoc = collection(
|
45 |
CommitDoc = collection(
|
|
... |
|
... |
265 |
removed.append(change.name)
|
267 |
removed.append(change.name)
|
266 |
elif change.lhs_id is None:
|
268 |
elif change.lhs_id is None:
|
267 |
added.append(change.name)
|
269 |
added.append(change.name)
|
268 |
else:
|
270 |
else:
|
269 |
changed.append(change.name)
|
271 |
changed.append(change.name)
|
|
|
272 |
prev_commit = self.log(1, 1)[0]
|
|
|
273 |
for r_name in removed[:]:
|
|
|
274 |
r_blob = prev_commit.tree.get_obj_by_path(r_name)
|
|
|
275 |
r_type = 'blob' if isinstance(r_blob, Blob) else 'tree'
|
|
|
276 |
best = dict(ratio=0, name='')
|
|
|
277 |
for a_name in added:
|
|
|
278 |
a_blob = self.tree.get_obj_by_path(a_name)
|
|
|
279 |
if r_type == 'tree':
|
|
|
280 |
if isinstance(a_blob, Tree):
|
|
|
281 |
if r_blob._id == a_blob._id:
|
|
|
282 |
best['ratio'] = 100
|
|
|
283 |
best['name'] = a_name
|
|
|
284 |
break;
|
|
|
285 |
else:
|
|
|
286 |
diff = SequenceMatcher(None, r_blob.text, a_blob.text)
|
|
|
287 |
if diff.ratio() > best['ratio']:
|
|
|
288 |
best['ratio'] = diff.ratio()
|
|
|
289 |
best['name'] = a_name
|
|
|
290 |
if best['ratio'] > DIFF_SIMILARITY_THRESHOLD:
|
|
|
291 |
copied.append(dict(old=r_name, new=a_name))
|
|
|
292 |
removed.remove(r_name)
|
|
|
293 |
added.remove(best['name'])
|
270 |
return Object(
|
294 |
return Object(
|
271 |
added=added, removed=removed,
|
295 |
added=added, removed=removed,
|
272 |
changed=changed, copied=copied)
|
296 |
changed=changed, copied=copied)
|
273 |
|
297 |
|
274 |
def get_path(self, path):
|
298 |
def get_path(self, path):
|
|
... |
|
... |
309 |
obj = self.query.get(_id=oid)
|
333 |
obj = self.query.get(_id=oid)
|
310 |
if obj is None: raise KeyError, name
|
334 |
if obj is None: raise KeyError, name
|
311 |
obj.set_context(self, name)
|
335 |
obj.set_context(self, name)
|
312 |
return obj
|
336 |
return obj
|
313 |
|
337 |
|
314 |
def get_blob_by_path(self, path):
|
338 |
def get_obj_by_path(self, path):
|
315 |
path = path.split('/')
|
339 |
path = path.split('/')
|
316 |
obj = self
|
340 |
obj = self
|
317 |
for p in path:
|
341 |
for p in path:
|
318 |
try:
|
342 |
try:
|
319 |
obj = obj[p]
|
343 |
obj = obj[p]
|
320 |
except KeyError:
|
344 |
except KeyError:
|
321 |
return None
|
345 |
return None
|
|
|
346 |
return obj
|
|
|
347 |
|
|
|
348 |
def get_blob_by_path(self, path):
|
|
|
349 |
obj = self.get_obj_by_path(path)
|
322 |
return obj if isinstance(obj, Blob) else None
|
350 |
return obj if isinstance(obj, Blob) else None
|
323 |
|
351 |
|
324 |
def set_context(self, commit_or_tree, name=None):
|
352 |
def set_context(self, commit_or_tree, name=None):
|
325 |
assert commit_or_tree is not self
|
353 |
assert commit_or_tree is not self
|
326 |
self.repo = commit_or_tree.repo
|
354 |
self.repo = commit_or_tree.repo
|