Merge lp:~jelmer/loggerhead/no-file-ids into lp:loggerhead

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Colin Watson
Approved revision: 523
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: lp:~jelmer/loggerhead/no-file-ids
Merge into: lp:loggerhead
Diff against target: 705 lines (+102/-175)
15 files modified
loggerhead/controllers/annotate_ui.py (+3/-7)
loggerhead/controllers/changelog_ui.py (+5/-10)
loggerhead/controllers/download_ui.py (+1/-6)
loggerhead/controllers/inventory_ui.py (+7/-15)
loggerhead/controllers/revision_ui.py (+5/-5)
loggerhead/controllers/view_ui.py (+3/-13)
loggerhead/history.py (+51/-73)
loggerhead/templates/changelog.pt (+1/-1)
loggerhead/templates/inventory.pt (+3/-3)
loggerhead/templates/search-box.pt (+1/-2)
loggerhead/templates/view.pt (+1/-1)
loggerhead/tests/fixtures.py (+2/-3)
loggerhead/tests/test_controllers.py (+13/-25)
loggerhead/tests/test_simple.py (+3/-6)
loggerhead/util.py (+3/-5)
To merge this branch: bzr merge lp:~jelmer/loggerhead/no-file-ids
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+426375@code.launchpad.net

Commit message

Avoid use of file ids - use paths instead.

Description of the change

Avoid use of file ids - use paths instead.

This prepares loggerhead for upcoming Breezy changes, which remove file ids
from the primary API. The goal behind this is to make the implementation
of non-Bazaar filesystems simpler.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote :

This does break some old (horrible) URLs, but it seems ultimately necessary, so I'm OK with this. Let's see what the test suite makes of it.

review: Approve
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote :
Revision history for this message
Otto Co-Pilot (otto-copilot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'loggerhead/controllers/annotate_ui.py'
--- loggerhead/controllers/annotate_ui.py 2020-07-14 16:41:12 +0000
+++ loggerhead/controllers/annotate_ui.py 2022-07-06 12:59:30 +0000
@@ -24,14 +24,10 @@
2424
25class AnnotateUI(ViewUI):25class AnnotateUI(ViewUI):
2626
27 def annotate_file(self, info):27 def annotate_file(self, path, info):
28 file_id = info['file_id']
29 revid = info['change'].revid28 revid = info['change'].revid
30 if not isinstance(file_id, bytes):
31 raise TypeError(file_id)
32 if not isinstance(revid, bytes):29 if not isinstance(revid, bytes):
33 raise TypeError(revid)30 raise TypeError(revid)
34 path = self._history.get_path(revid, file_id)
3531
36 tree = self.tree_for(path, revid)32 tree = self.tree_for(path, revid)
3733
@@ -43,7 +39,7 @@
43 revisions = {}39 revisions = {}
4440
45 lineno = 041 lineno = 0
46 for (line_revid, text), lineno in zip(tree.annotate_iter(path, file_id), itertools.count(1)):42 for (line_revid, text), lineno in zip(tree.annotate_iter(path), itertools.count(1)):
47 if line_revid != last_line_revid:43 if line_revid != last_line_revid:
48 last_line_revid = line_revid44 last_line_revid = line_revid
4945
@@ -84,6 +80,6 @@
8480
85 def get_values(self, path, kwargs, headers):81 def get_values(self, path, kwargs, headers):
86 values = super(AnnotateUI, self).get_values(path, kwargs, headers)82 values = super(AnnotateUI, self).get_values(path, kwargs, headers)
87 values['annotated'] = self.annotate_file(values)83 values['annotated'] = self.annotate_file(path, values)
8884
89 return values85 return values
9086
=== modified file 'loggerhead/controllers/changelog_ui.py'
--- loggerhead/controllers/changelog_ui.py 2020-07-08 17:14:19 +0000
+++ loggerhead/controllers/changelog_ui.py 2022-07-06 12:59:30 +0000
@@ -35,21 +35,16 @@
35 def get_values(self, path, kwargs, headers):35 def get_values(self, path, kwargs, headers):
36 history = self._history36 history = self._history
37 revid = self.get_revid()37 revid = self.get_revid()
38 filter_file_id = kwargs.get('filter_file_id', None)38 filter_path = kwargs.get('filter_path', path)
39 if filter_file_id is not None:
40 filter_file_id = urlutils.unquote_to_bytes(osutils.safe_utf8(filter_file_id))
41 query = kwargs.get('q', None)39 query = kwargs.get('q', None)
42 start_revid = history.fix_revid(kwargs.get('start_revid', None))40 start_revid = history.fix_revid(kwargs.get('start_revid', None))
43 orig_start_revid = start_revid41 orig_start_revid = start_revid
44 pagesize = 20#int(config.get('pagesize', '20'))42 pagesize = 20 #int(config.get('pagesize', '20'))
45 search_failed = False43 search_failed = False
4644
47 if filter_file_id is None and path is not None:
48 filter_file_id = history.get_file_id(revid, path)
49
50 try:45 try:
51 revid, start_revid, revid_list = history.get_view(46 revid, start_revid, revid_list = history.get_view(
52 revid, start_revid, filter_file_id, query,47 revid, start_revid, filter_path, query,
53 extra_rev_count=pagesize+1)48 extra_rev_count=pagesize+1)
54 util.set_context(kwargs)49 util.set_context(kwargs)
5550
@@ -76,7 +71,7 @@
7671
77 navigation = util.Container(72 navigation = util.Container(
78 pagesize=pagesize, revid=revid, start_revid=start_revid,73 pagesize=pagesize, revid=revid, start_revid=start_revid,
79 revid_list=revid_list, filter_file_id=filter_file_id,74 revid_list=revid_list, filter_path=filter_path,
80 scan_url='/changes', branch=self._branch, feed=True, history=history)75 scan_url='/changes', branch=self._branch, feed=True, history=history)
81 if query is not None:76 if query is not None:
82 navigation.query = query77 navigation.query = query
@@ -104,7 +99,7 @@
104 'history': history,99 'history': history,
105 'revid': revid,100 'revid': revid,
106 'navigation': navigation,101 'navigation': navigation,
107 'filter_file_id': filter_file_id,102 'filter_path': filter_path,
108 'start_revid': start_revid,103 'start_revid': start_revid,
109 'viewing_from': (orig_start_revid is not None) and104 'viewing_from': (orig_start_revid is not None) and
110 (orig_start_revid != history.last_revid),105 (orig_start_revid != history.last_revid),
111106
=== modified file 'loggerhead/controllers/download_ui.py'
--- loggerhead/controllers/download_ui.py 2020-07-08 17:12:21 +0000
+++ loggerhead/controllers/download_ui.py 2022-07-06 12:59:30 +0000
@@ -61,12 +61,7 @@
61 try:61 try:
62 path, filename, content = h.get_file(args[1], revid)62 path, filename, content = h.get_file(args[1], revid)
63 except (NoSuchFile, NoSuchRevision):63 except (NoSuchFile, NoSuchRevision):
64 # Compatibility API for /download/rev_id/file_id/<filename>64 raise httpexceptions.HTTPNotFound()
65 try:
66 path, filename, content = h.get_file_by_fileid(
67 args[1].encode('UTF-8'), revid)
68 except (NoSuchId, NoSuchRevision):
69 raise httpexceptions.HTTPNotFound()
70 mime_type, encoding = mimetypes.guess_type(filename)65 mime_type, encoding = mimetypes.guess_type(filename)
71 if mime_type is None:66 if mime_type is None:
72 mime_type = 'application/octet-stream'67 mime_type = 'application/octet-stream'
7368
=== modified file 'loggerhead/controllers/inventory_ui.py'
--- loggerhead/controllers/inventory_ui.py 2018-11-01 21:48:40 +0000
+++ loggerhead/controllers/inventory_ui.py 2022-07-06 12:59:30 +0000
@@ -95,7 +95,7 @@
95 file = util.Container(95 file = util.Container(
96 filename=entry.name, executable=entry.executable,96 filename=entry.name, executable=entry.executable,
97 kind=entry.kind, absolutepath=child_path,97 kind=entry.kind, absolutepath=child_path,
98 file_id=entry.file_id, size=size, revid=child_revision,98 size=size, revid=child_revision,
99 change=change_dict[child_revision], contents_changed_rev=contents_changed_rev)99 change=change_dict[child_revision], contents_changed_rev=contents_changed_rev)
100 file_list.append(file)100 file_list.append(file)
101101
@@ -125,23 +125,15 @@
125 except errors.NoSuchRevision:125 except errors.NoSuchRevision:
126 raise HTTPNotFound()126 raise HTTPNotFound()
127127
128 file_id = kwargs.get('file_id', None)
129 start_revid = kwargs.get('start_revid', None)128 start_revid = kwargs.get('start_revid', None)
130 sort_type = kwargs.get('sort', 'filename')129 sort_type = kwargs.get('sort', 'filename')
131130
132 if path is not None:131 if path is None:
133 path = path.rstrip('/')132 path = "/"
134 file_id = rev_tree.path2id(path)133
135 if file_id is None:134 path = path.rstrip('/')
136 raise HTTPNotFound()135 if not rev_tree.has_filename(path) and not is_null_rev(revid):
137 else:136 raise HTTPNotFound()
138 if file_id is None:
139 path = ''
140 else:
141 try:
142 path = rev_tree.id2path(file_id)
143 except errors.NoSuchId:
144 raise HTTPNotFound()
145137
146 # Are we at the top of the tree138 # Are we at the top of the tree
147 if path in ['/', '']:139 if path in ['/', '']:
148140
=== modified file 'loggerhead/controllers/revision_ui.py'
--- loggerhead/controllers/revision_ui.py 2021-03-29 11:18:58 +0000
+++ loggerhead/controllers/revision_ui.py 2022-07-06 12:59:30 +0000
@@ -46,7 +46,7 @@
46 h = self._history46 h = self._history
47 revid = self.get_revid()47 revid = self.get_revid()
4848
49 filter_file_id = kwargs.get('filter_file_id', None)49 filter_path = kwargs.get('filter_path', None)
50 start_revid = h.fix_revid(kwargs.get('start_revid', None))50 start_revid = h.fix_revid(kwargs.get('start_revid', None))
51 query = kwargs.get('q', None)51 query = kwargs.get('q', None)
52 compare_revid = h.fix_revid(kwargs.get('compare_revid', None))52 compare_revid = h.fix_revid(kwargs.get('compare_revid', None))
@@ -56,7 +56,7 @@
56 try:56 try:
57 revid, start_revid, revid_list = h.get_view(revid,57 revid, start_revid, revid_list = h.get_view(revid,
58 start_revid,58 start_revid,
59 filter_file_id,59 filter_path,
60 query)60 query)
61 except BaseException:61 except BaseException:
62 self.log.exception('Exception fetching changes')62 self.log.exception('Exception fetching changes')
@@ -102,12 +102,12 @@
102 super(RevisionUI, self).add_template_values(values)102 super(RevisionUI, self).add_template_values(values)
103 remember = self._history.fix_revid(self.kwargs.get('remember', None))103 remember = self._history.fix_revid(self.kwargs.get('remember', None))
104 query = self.kwargs.get('q', None)104 query = self.kwargs.get('q', None)
105 filter_file_id = self.kwargs.get('filter_file_id', None)105 filter_path = self.kwargs.get('filter_path', None)
106 start_revid = self.kwargs['start_revid']106 start_revid = self.kwargs['start_revid']
107 navigation = util.Container(107 navigation = util.Container(
108 revid_list=self.revid_list, revid=values['revid'],108 revid_list=self.revid_list, revid=values['revid'],
109 start_revid=start_revid,109 start_revid=start_revid,
110 filter_file_id=filter_file_id, pagesize=1,110 filter_path=filter_path, pagesize=1,
111 scan_url='/revision', branch=self._branch, feed=True,111 scan_url='/revision', branch=self._branch, feed=True,
112 history=self._history)112 history=self._history)
113 if query is not None:113 if query is not None:
@@ -161,7 +161,7 @@
161 'navigation': navigation,161 'navigation': navigation,
162 'remember': remember,162 'remember': remember,
163 'compare_revid': self.compare_revid,163 'compare_revid': self.compare_revid,
164 'filter_file_id': filter_file_id,164 'filter_path': filter_path,
165 'diff_chunks': diff_chunks,165 'diff_chunks': diff_chunks,
166 'query': query,166 'query': query,
167 'can_export': can_export,167 'can_export': can_export,
168168
=== modified file 'loggerhead/controllers/view_ui.py'
--- loggerhead/controllers/view_ui.py 2021-11-15 14:40:11 +0000
+++ loggerhead/controllers/view_ui.py 2022-07-06 12:59:30 +0000
@@ -99,19 +99,10 @@
99 history = self._history99 history = self._history
100 branch = history._branch100 branch = history._branch
101 revid = self.get_revid()101 revid = self.get_revid()
102 file_id = kwargs.get('file_id', None)102 if path is None:
103 if file_id is not None:103 raise HTTPBadRequest('No filename provided to view')
104 file_id = urlutils.unquote_to_bytes(osutils.safe_utf8(file_id))
105 if (file_id is None) and (path is None):
106 raise HTTPBadRequest('No file_id or filename '
107 'provided to view')
108104
109 try:105 if not history.file_exists(revid, path):
110 if file_id is None:
111 file_id = history.get_file_id(revid, path)
112 if path is None:
113 path = history.get_path(revid, file_id)
114 except (NoSuchId, NoSuchRevision):
115 raise HTTPNotFound()106 raise HTTPNotFound()
116107
117 filename = os.path.basename(path)108 filename = os.path.basename(path)
@@ -151,7 +142,6 @@
151 # checking whether we're in "annotated" mode.142 # checking whether we're in "annotated" mode.
152 'annotated': {},143 'annotated': {},
153 'revno_url': revno_url,144 'revno_url': revno_url,
154 'file_id': file_id,
155 'file_path': path,145 'file_path': path,
156 'filename': filename,146 'filename': filename,
157 'navigation': navigation,147 'navigation': navigation,
158148
=== modified file 'loggerhead/history.py'
--- loggerhead/history.py 2021-11-15 14:40:11 +0000
+++ loggerhead/history.py 2022-07-06 12:59:30 +0000
@@ -34,7 +34,6 @@
34import textwrap34import textwrap
35import threading35import threading
3636
37from breezy import version_info as breezy_version
38from breezy import tag37from breezy import tag
39import breezy.branch38import breezy.branch
40import breezy.delta39import breezy.delta
@@ -127,18 +126,11 @@
127 except breezy.errors.NoSuchFile:126 except breezy.errors.NoSuchFile:
128 return breezy.revision.NULL_REVISION127 return breezy.revision.NULL_REVISION
129128
130 if breezy_version >= (3, 1):129 def report(self, paths, versioned, renamed, copied, modified,
131 def report(self, paths, versioned, renamed, copied, modified,130 exe_change, kind):
132 exe_change, kind):131 return self._report(
133 return self._report(132 paths, versioned, renamed, copied,
134 paths, versioned, renamed, copied,133 modified, exe_change, kind)
135 modified, exe_change, kind)
136 else:
137 def report(self, file_id, paths, versioned, renamed, modified,
138 exe_change, kind):
139 return self._report(
140 paths, versioned, renamed, None,
141 modified, exe_change, kind)
142134
143 def _report(self, paths, versioned, renamed, copied, modified,135 def _report(self, paths, versioned, renamed, copied, modified,
144 exe_change, kind):136 exe_change, kind):
@@ -376,6 +368,7 @@
376 def get_short_revision_history_by_fileid(self, file_id):368 def get_short_revision_history_by_fileid(self, file_id):
377 # FIXME: would be awesome if we could get, for a folder, the list of369 # FIXME: would be awesome if we could get, for a folder, the list of
378 # revisions where items within that folder changed.i370 # revisions where items within that folder changed.i
371 # TODO(jelmer): Avoid versionedfile-specific texts
379 possible_keys = [(file_id, revid) for revid in self._rev_indices]372 possible_keys = [(file_id, revid) for revid in self._rev_indices]
380 get_parent_map = self._branch.repository.texts.get_parent_map373 get_parent_map = self._branch.repository.texts.get_parent_map
381 # We chunk the requests as this works better with GraphIndex.374 # We chunk the requests as this works better with GraphIndex.
@@ -478,24 +471,6 @@
478 revid = revid.encode('utf-8')471 revid = revid.encode('utf-8')
479 return revid472 return revid
480473
481 def get_file_view(self, revid, file_id):
482 """
483 Given a revid and optional path, return a (revlist, revid) for
484 navigation through the current scope: from the revid (or the latest
485 revision) back to the original revision.
486
487 If file_id is None, the entire revision history is the list scope.
488 """
489 if revid is None:
490 revid = self.last_revid
491 if file_id is not None:
492 revlist = list(
493 self.get_short_revision_history_by_fileid(file_id))
494 revlist = self.get_revids_from(revlist, revid)
495 else:
496 revlist = self.get_revids_from(None, revid)
497 return revlist
498
499 @staticmethod474 @staticmethod
500 def _iterate_sufficiently(iterable, stop_at, extra_rev_count):475 def _iterate_sufficiently(iterable, stop_at, extra_rev_count):
501 """Return a list of iterable.476 """Return a list of iterable.
@@ -522,15 +497,33 @@
522 result.append(n)497 result.append(n)
523 return result498 return result
524499
525 def get_view(self, revid, start_revid, file_id, query=None,500 def _get_file_view(self, revid, file_id):
501 """
502 Given a revid and optional path, return a (revlist, revid) for
503 navigation through the current scope: from the revid (or the latest
504 revision) back to the original revision.
505
506 If file_id is None, the entire revision history is the list scope.
507 """
508 if revid is None:
509 revid = self.last_revid
510 if file_id is not None:
511 revlist = list(
512 self.get_short_revision_history_by_fileid(file_id))
513 revlist = self.get_revids_from(revlist, revid)
514 else:
515 revlist = self.get_revids_from(None, revid)
516 return revlist
517
518 def get_view(self, revid, start_revid, path, query=None,
526 extra_rev_count=None):519 extra_rev_count=None):
527 """520 """
528 use the URL parameters (revid, start_revid, file_id, and query) to521 use the URL parameters (revid, start_revid, path, and query) to
529 determine the revision list we're viewing (start_revid, file_id, query)522 determine the revision list we're viewing (start_revid, path, query)
530 and where we are in it (revid).523 and where we are in it (revid).
531524
532 - if a query is given, we're viewing query results.525 - if a query is given, we're viewing query results.
533 - if a file_id is given, we're viewing revisions for a specific526 - if a path is given, we're viewing revisions for a specific
534 file.527 file.
535 - if a start_revid is given, we're viewing the branch from a528 - if a start_revid is given, we're viewing the branch from a
536 specific revision up the tree.529 specific revision up the tree.
@@ -548,14 +541,19 @@
548 - start_revid: starting revision of this view541 - start_revid: starting revision of this view
549 - revid_list: list of revision ids for this view542 - revid_list: list of revision ids for this view
550543
551 file_id and query are never changed so aren't returned, but they may544 path and query are never changed so aren't returned, but they may
552 contain vital context for future url navigation.545 contain vital context for future url navigation.
553 """546 """
554 if start_revid is None:547 if start_revid is None:
555 start_revid = self.last_revid548 start_revid = self.last_revid
556549
557 if query is None:550 if query is None:
558 revid_list = self.get_file_view(start_revid, file_id)551 repo = self._branch.repository
552 if path is not None:
553 file_id = repo.revision_tree(start_revid).path2id(path)
554 else:
555 file_id = None
556 revid_list = self._get_file_view(start_revid, file_id)
559 revid_list = self._iterate_sufficiently(revid_list, revid,557 revid_list = self._iterate_sufficiently(revid_list, revid,
560 extra_rev_count)558 extra_rev_count)
561 if revid is None:559 if revid is None:
@@ -563,15 +561,17 @@
563 if revid not in revid_list:561 if revid not in revid_list:
564 # if the given revid is not in the revlist, use a revlist that562 # if the given revid is not in the revlist, use a revlist that
565 # starts at the given revid.563 # starts at the given revid.
566 revid_list = self.get_file_view(revid, file_id)564 revid_list = self._get_file_view(revid, file_id)
567 revid_list = self._iterate_sufficiently(revid_list, revid,565 revid_list = self._iterate_sufficiently(revid_list, revid,
568 extra_rev_count)566 extra_rev_count)
569 start_revid = revid567 start_revid = revid
570 return revid, start_revid, revid_list568 return revid, start_revid, revid_list
569 else:
570 file_id = None
571571
572 # potentially limit the search572 # potentially limit the search
573 if file_id is not None:573 if file_id is not None:
574 revid_list = self.get_file_view(start_revid, file_id)574 revid_list = self._get_file_view(start_revid, file_id)
575 else:575 else:
576 revid_list = None576 revid_list = None
577 revid_list = search.search_revisions(self._branch, query)577 revid_list = search.search_revisions(self._branch, query)
@@ -588,18 +588,13 @@
588 def revision_tree(self, revid):588 def revision_tree(self, revid):
589 return self._branch.repository.revision_tree(revid)589 return self._branch.repository.revision_tree(revid)
590590
591 def get_path(self, revid, file_id):591 def file_exists(self, revid, path):
592 if (file_id is None) or (file_id == ''):592 if (len(path) > 0) and not path.startswith('/'):
593 return ''593 path = '/' + path
594 path = self.revision_tree(revid).id2path(file_id)594 try:
595 if (len(path) > 0) and not path.startswith('/'):595 return self.revision_tree(revid).has_filename(path)
596 path = '/' + path596 except breezy.errors.NoSuchRevision:
597 return path597 return False
598
599 def get_file_id(self, revid, path):
600 if (len(path) > 0) and not path.startswith('/'):
601 path = '/' + path
602 return self.revision_tree(revid).path2id(path)
603598
604 def get_merge_point_list(self, revid):599 def get_merge_point_list(self, revid):
605 """600 """
@@ -786,32 +781,15 @@
786 return (display_path, breezy.osutils.basename(path),781 return (display_path, breezy.osutils.basename(path),
787 rev_tree.get_file_text(path))782 rev_tree.get_file_text(path))
788783
789 def get_file_by_fileid(self, fileid, revid):
790 """Returns (path, filename, file contents)"""
791 if not isinstance(fileid, bytes):
792 raise TypeError(fileid)
793 if not isinstance(revid, bytes):
794 raise TypeError(revid)
795 rev_tree = self._branch.repository.revision_tree(revid)
796 path = rev_tree.id2path(fileid)
797 display_path = path
798 if not display_path.startswith('/'):
799 path = '/' + path
800 return (display_path, breezy.osutils.basename(path),
801 rev_tree.get_file_text(path))
802
803 def file_changes_for_revision_ids(self, old_revid, new_revid):784 def file_changes_for_revision_ids(self, old_revid, new_revid):
804 """785 """
805 Return a nested data structure containing the changes in a delta::786 Return a nested data structure containing the changes in a delta::
806787
807 added: list((filename, file_id)),788 added: list((filename)),
808 renamed: list((old_filename, new_filename, file_id)),789 renamed: list((old_filename, new_filename)),
809 deleted: list((filename, file_id)),790 deleted: list((filename)),
810 modified: list(791 modified: list((filename)),
811 filename: str,792 text_changes: list((filename)),
812 file_id: str,
813 ),
814 text_changes: list((filename, file_id)),
815 """793 """
816 repo = self._branch.repository794 repo = self._branch.repository
817 if (breezy.revision.is_null(old_revid) or795 if (breezy.revision.is_null(old_revid) or
818796
=== modified file 'loggerhead/templates/changelog.pt'
--- loggerhead/templates/changelog.pt 2012-02-02 07:42:24 +0000
+++ loggerhead/templates/changelog.pt 2022-07-06 12:59:30 +0000
@@ -39,7 +39,7 @@
39 </tal:no-link>39 </tal:no-link>
40 <tal:block condition="changes">40 <tal:block condition="changes">
41 &#187; Changes41 &#187; Changes
42 <tal:block condition="filter_file_id">to <span tal:content="python:history.get_path(revid, filter_file_id)" /></tal:block>42 <tal:block condition="filter_path">to <span tal:content="filter_path" /></tal:block>
43 <tal:block condition="start_revid">from revision43 <tal:block condition="start_revid">from revision
44 <span tal:content="python:history.get_revno(start_revid)"/>44 <span tal:content="python:history.get_revno(start_revid)"/>
45 </tal:block>45 </tal:block>
4646
=== modified file 'loggerhead/templates/inventory.pt'
--- loggerhead/templates/inventory.pt 2018-10-20 16:06:44 +0000
+++ loggerhead/templates/inventory.pt 2022-07-06 12:59:30 +0000
@@ -94,7 +94,7 @@
94 <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>94 <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>
95 <td class="autcell" tal:content="python:file.change.comment[:50]"></td>95 <td class="autcell" tal:content="python:file.change.comment[:50]"></td>
96 <td class="timedate2"></td><!-- not showing sizes of folders -->96 <td class="timedate2"></td><!-- not showing sizes of folders -->
97 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_file_id=file.file_id);97 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_path=file.absolutepath);
98 title string:Show revision ${file/change/revno}">98 title string:Show revision ${file/change/revno}">
99 <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif')" alt="Diff" />99 <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif')" alt="Diff" />
100 </a>100 </a>
@@ -119,7 +119,7 @@
119 <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>119 <td class="date" tal:content="python:util.hide_email(file.change.committer)"></td>
120 <td class="autcell" tal:content="python:file.change.comment[:50]"></td>120 <td class="autcell" tal:content="python:file.change.comment[:50]"></td>
121 <td class="timedate2">.</td>121 <td class="timedate2">.</td>
122 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_file_id=file.file_id);122 <td class="expcell"><a tal:attributes="href python:url(['/changes'], start_revid=start_revid, filter_path=file.absolutepath);
123 title string:Show revision ${file/change/revno}">123 title string:Show revision ${file/change/revno}">
124 <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif');124 <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif');
125 title string:Show revision ${file/change/revno}" />125 title string:Show revision ${file/change/revno}" />
@@ -157,7 +157,7 @@
157 </a>157 </a>
158 </td>158 </td>
159 <td class="expcell">159 <td class="expcell">
160 <a tal:attributes="href python:url(['/download', file.revid.decode('utf-8'), file.file_id.decode('utf-8'), file.filename]);160 <a tal:attributes="href python:url(['/download', file.revid.decode('utf-8'), file.filename]);
161 title string:Download ${file/filename} at revision ${file/change/revno}">161 title string:Download ${file/filename} at revision ${file/change/revno}">
162 <img tal:attributes="src python:branch.static_url('/static/images/ico_file_download.gif')" alt="Download File" />162 <img tal:attributes="src python:branch.static_url('/static/images/ico_file_download.gif')" alt="Download File" />
163 </a>163 </a>
164164
=== modified file 'loggerhead/templates/search-box.pt'
--- loggerhead/templates/search-box.pt 2008-08-13 17:24:10 +0000
+++ loggerhead/templates/search-box.pt 2022-07-06 12:59:30 +0000
@@ -1,8 +1,7 @@
1<tal:search-box>1<tal:search-box>
2 <form tal:attributes="action python:branch.url('/changes',2 <form tal:attributes="action python:branch.url('/changes',
3 start_revid=getattr(navigation,3 start_revid=getattr(navigation,
4 'start_revid', None),4 'start_revid', None))">
5 file_id=getattr(navigation, 'file_id', None))">
6 <label>search:</label>5 <label>search:</label>
7 <input type="search" name="q" id="q" autocomplete="off" onblur="hide_search();" />6 <input type="search" name="q" id="q" autocomplete="off" onblur="hide_search();" />
8 </form>7 </form>
98
=== modified file 'loggerhead/templates/view.pt'
--- loggerhead/templates/view.pt 2020-06-04 19:21:17 +0000
+++ loggerhead/templates/view.pt 2022-07-06 12:59:30 +0000
@@ -59,7 +59,7 @@
59 <a tal:attributes="href python:url(['/revision', change.revno], clear=1)">view revision</a>59 <a tal:attributes="href python:url(['/revision', change.revno], clear=1)">view revision</a>
60 </li>60 </li>
61 <li>61 <li>
62 <a tal:attributes="href python:url(['/changes'], clear=1, filter_file_id=file_id)"62 <a tal:attributes="href python:url(['/changes'], clear=1, filter_path=file_path)"
63 >view changes to this file</a>63 >view changes to this file</a>
64 </li>64 </li>
65 <li id="last">65 <li id="last">
6666
=== modified file 'loggerhead/tests/fixtures.py'
--- loggerhead/tests/fixtures.py 2018-10-20 13:45:31 +0000
+++ loggerhead/tests/fixtures.py 2022-07-06 12:59:30 +0000
@@ -36,8 +36,7 @@
36 filenames = ['myfilename', 'anotherfile<']36 filenames = ['myfilename', 'anotherfile<']
37 self.testcase.build_tree_contents(37 self.testcase.build_tree_contents(
38 (filename, self.filecontents) for filename in filenames)38 (filename, self.filecontents) for filename in filenames)
39 for filename in filenames:39 self.tree.add(filenames)
40 self.tree.add(filename, ('%s-id' % filename).encode('utf-8'))40 self.path = 'myfilename'
41 self.fileid = self.tree.path2id('myfilename')
42 self.msg = 'a very exciting commit message <'41 self.msg = 'a very exciting commit message <'
43 self.revid = self.tree.commit(message=self.msg)42 self.revid = self.tree.commit(message=self.msg)
4443
=== modified file 'loggerhead/tests/test_controllers.py'
--- loggerhead/tests/test_controllers.py 2021-03-29 11:18:58 +0000
+++ loggerhead/tests/test_controllers.py 2022-07-06 12:59:30 +0000
@@ -221,12 +221,12 @@
221221
222class TestAnnotateUI(BasicTests):222class TestAnnotateUI(BasicTests):
223223
224 def make_annotate_ui_for_file_history(self, file_id, rev_ids_texts):224 def make_annotate_ui_for_file_history(self, filename, rev_ids_texts):
225 tree = self.make_branch_and_tree('.')225 tree = self.make_branch_and_tree('.')
226 self.build_tree_contents([('filename', '')])226 self.build_tree_contents([(filename, '')])
227 tree.add(['filename'], [file_id])227 tree.add([filename])
228 for rev_id, text, message in rev_ids_texts:228 for rev_id, text, message in rev_ids_texts:
229 self.build_tree_contents([('filename', text)])229 self.build_tree_contents([(filename, text)])
230 tree.commit(rev_id=rev_id, message=message)230 tree.commit(rev_id=rev_id, message=message)
231 tree.branch.lock_read()231 tree.branch.lock_read()
232 self.addCleanup(tree.branch.unlock)232 self.addCleanup(tree.branch.unlock)
@@ -235,12 +235,11 @@
235235
236 def test_annotate_file(self):236 def test_annotate_file(self):
237 history = [(b'rev1', b'old\nold\n', '.'), (b'rev2', b'new\nold\n', '.')]237 history = [(b'rev1', b'old\nold\n', '.'), (b'rev2', b'new\nold\n', '.')]
238 ann_ui = self.make_annotate_ui_for_file_history(b'file_id', history)238 ann_ui = self.make_annotate_ui_for_file_history('filename', history)
239 # A lot of this state is set up by __call__, but we'll do it directly239 # A lot of this state is set up by __call__, but we'll do it directly
240 # here.240 # here.
241 ann_ui.args = ['rev2']241 ann_ui.args = ['rev2']
242 annotate_info = ann_ui.get_values(u'filename',242 annotate_info = ann_ui.get_values(u'filename', kwargs={}, headers={})
243 kwargs={'file_id': 'file_id'}, headers={})
244 annotated = annotate_info['annotated']243 annotated = annotate_info['annotated']
245 self.assertEqual(2, len(annotated))244 self.assertEqual(2, len(annotated))
246 self.assertEqual('2', annotated[1].change.revno)245 self.assertEqual('2', annotated[1].change.revno)
@@ -249,32 +248,30 @@
249 def test_annotate_empty_comment(self):248 def test_annotate_empty_comment(self):
250 # Testing empty comment handling without breaking249 # Testing empty comment handling without breaking
251 history = [(b'rev1', b'old\nold\n', '.'), (b'rev2', b'new\nold\n', '')]250 history = [(b'rev1', b'old\nold\n', '.'), (b'rev2', b'new\nold\n', '')]
252 ann_ui = self.make_annotate_ui_for_file_history(b'file_id', history)251 ann_ui = self.make_annotate_ui_for_file_history('filename', history)
253 ann_ui.args = ['rev2']252 ann_ui.args = ['rev2']
254 ann_ui.get_values(253 ann_ui.get_values(u'filename', kwargs={}, headers={})
255 u'filename', kwargs={'file_id': 'file_id'}, headers={})
256254
257 def test_annotate_file_zero_sized(self):255 def test_annotate_file_zero_sized(self):
258 # Test against a zero-sized file without breaking. No annotation256 # Test against a zero-sized file without breaking. No annotation
259 # must be present.257 # must be present.
260 history = [(b'rev1', b'', '.')]258 history = [(b'rev1', b'', '.')]
261 ann_ui = self.make_annotate_ui_for_file_history(b'file_id', history)259 ann_ui = self.make_annotate_ui_for_file_history('filename', history)
262 ann_ui.args = ['rev1']260 ann_ui.args = ['rev1']
263 annotate_info = ann_ui.get_values(u'filename',261 annotate_info = ann_ui.get_values(u'filename', kwargs={}, headers={})
264 kwargs={'file_id': 'file_id'}, headers={})
265 annotated = annotate_info['annotated']262 annotated = annotate_info['annotated']
266 self.assertEqual(0, len(annotated))263 self.assertEqual(0, len(annotated))
267264
268 def test_annotate_nonexistent_file(self):265 def test_annotate_nonexistent_file(self):
269 history = [(b'rev1', b'', '.')]266 history = [(b'rev1', b'', '.')]
270 ann_ui = self.make_annotate_ui_for_file_history(b'file_id', history)267 ann_ui = self.make_annotate_ui_for_file_history('filename', history)
271 ann_ui.args = ['rev1']268 ann_ui.args = ['rev1']
272 self.assertRaises(269 self.assertRaises(
273 HTTPNotFound, ann_ui.get_values, u'not-filename', {}, {})270 HTTPNotFound, ann_ui.get_values, u'not-filename', {}, {})
274271
275 def test_annotate_nonexistent_rev(self):272 def test_annotate_nonexistent_rev(self):
276 history = [(b'rev1', b'', '.')]273 history = [(b'rev1', b'', '.')]
277 ann_ui = self.make_annotate_ui_for_file_history(b'file_id', history)274 ann_ui = self.make_annotate_ui_for_file_history('filename', history)
278 ann_ui.args = ['norev']275 ann_ui.args = ['norev']
279 self.assertRaises(276 self.assertRaises(
280 HTTPNotFound, ann_ui.get_values, u'not-filename', {}, {})277 HTTPNotFound, ann_ui.get_values, u'not-filename', {}, {})
@@ -433,15 +430,6 @@
433 response,430 response,
434 MatchesDownloadHeaders('myfilename', 'application/octet-stream'))431 MatchesDownloadHeaders('myfilename', 'application/octet-stream'))
435432
436 def test_download_with_revid(self):
437 app = self.setUpLoggerhead()
438 response = app.get('/download/1/myfilename-id/myfilename')
439 self.assertEqual(
440 b'some\nmultiline\ndata\nwith<htmlspecialchars\n', response.body)
441 self.assertThat(
442 response,
443 MatchesDownloadHeaders('myfilename', 'application/octet-stream'))
444
445 def test_download_bad_revision(self):433 def test_download_bad_revision(self):
446 app = self.setUpLoggerhead()434 app = self.setUpLoggerhead()
447 e = self.assertRaises(435 e = self.assertRaises(
@@ -449,7 +437,7 @@
449 app.get, '/download/norev/myfilename')437 app.get, '/download/norev/myfilename')
450 self.assertContainsRe(str(e), '404 Not Found')438 self.assertContainsRe(str(e), '404 Not Found')
451439
452 def test_download_bad_fileid(self):440 def test_download_bad_filename(self):
453 app = self.setUpLoggerhead()441 app = self.setUpLoggerhead()
454 e = self.assertRaises(442 e = self.assertRaises(
455 AppError,443 AppError,
456444
=== modified file 'loggerhead/tests/test_simple.py'
--- loggerhead/tests/test_simple.py 2021-11-15 14:40:11 +0000
+++ loggerhead/tests/test_simple.py 2022-07-06 12:59:30 +0000
@@ -78,7 +78,7 @@
78 # XXX: This could be cleaned up more... -- mbp 2011-11-2578 # XXX: This could be cleaned up more... -- mbp 2011-11-25
79 self.useFixture(self.sample_branch_fixture)79 self.useFixture(self.sample_branch_fixture)
80 self.tree = self.sample_branch_fixture.tree80 self.tree = self.sample_branch_fixture.tree
81 self.fileid = self.sample_branch_fixture.fileid81 self.path = self.sample_branch_fixture.path
82 self.filecontents = self.sample_branch_fixture.filecontents82 self.filecontents = self.sample_branch_fixture.filecontents
83 self.msg = self.sample_branch_fixture.msg83 self.msg = self.sample_branch_fixture.msg
8484
@@ -95,7 +95,7 @@
9595
96 def test_changes_for_file(self):96 def test_changes_for_file(self):
97 app = self.setUpLoggerhead()97 app = self.setUpLoggerhead()
98 res = app.get('/changes?filter_file_id=myfilename-id')98 res = app.get('/changes?filter_path=%s' % self.path)
99 res.mustcontain(escape(self.msg))99 res.mustcontain(escape(self.msg))
100100
101 def test_changes_branch_from(self):101 def test_changes_branch_from(self):
@@ -111,7 +111,7 @@
111111
112 def test_annotate(self):112 def test_annotate(self):
113 app = self.setUpLoggerhead()113 app = self.setUpLoggerhead()
114 res = app.get('/annotate', params={'file_id': self.fileid})114 res = app.get('/annotate/1/%s' % self.path, params={})
115 # If pygments is installed, it inserts <span class="pyg" content into115 # If pygments is installed, it inserts <span class="pyg" content into
116 # the output, to trigger highlighting. And it specifically highlights116 # the output, to trigger highlighting. And it specifically highlights
117 # the &lt; that we are interested in seeing in the output.117 # the &lt; that we are interested in seeing in the output.
@@ -137,8 +137,6 @@
137 res.mustcontain('myfilename')137 res.mustcontain('myfilename')
138 res = app.get('/files/1/')138 res = app.get('/files/1/')
139 res.mustcontain('myfilename')139 res.mustcontain('myfilename')
140 res = app.get('/files/1/?file_id=' + self.tree.path2id('').decode('utf-8'))
141 res.mustcontain('myfilename')
142140
143 def test_inventory_bad_rev_404(self):141 def test_inventory_bad_rev_404(self):
144 app = self.setUpLoggerhead()142 app = self.setUpLoggerhead()
@@ -148,7 +146,6 @@
148 def test_inventory_bad_path_404(self):146 def test_inventory_bad_path_404(self):
149 app = self.setUpLoggerhead()147 app = self.setUpLoggerhead()
150 res = app.get('/files/1/hooha', status=404)148 res = app.get('/files/1/hooha', status=404)
151 res = app.get('/files/1?file_id=dssadsada', status=404)
152149
153 def test_revision(self):150 def test_revision(self):
154 app = self.setUpLoggerhead()151 app = self.setUpLoggerhead()
155152
=== modified file 'loggerhead/util.py'
--- loggerhead/util.py 2021-11-15 14:40:11 +0000
+++ loggerhead/util.py 2022-07-06 12:59:30 +0000
@@ -409,7 +409,7 @@
409 navigation.next_page_revid)409 navigation.next_page_revid)
410 start_revno = navigation.history.get_revno(navigation.start_revid)410 start_revno = navigation.history.get_revno(navigation.start_revid)
411411
412 params = {'filter_file_id': navigation.filter_file_id}412 params = {'filter_path': navigation.filter_path}
413 if getattr(navigation, 'query', None) is not None:413 if getattr(navigation, 'query', None) is not None:
414 params['q'] = navigation.query414 params['q'] = navigation.query
415415
@@ -533,9 +533,7 @@
533# the current beginning of navigation (navigation continues back to533# the current beginning of navigation (navigation continues back to
534# the original revision) -- this defines an 'alternate mainline'534# the original revision) -- this defines an 'alternate mainline'
535# when the user navigates into a branch.535# when the user navigates into a branch.
536# - file_id536# - filter_path
537# the file being looked at
538# - filter_file_id
539# if navigating the revisions that touched a file537# if navigating the revisions that touched a file
540# - q (query)538# - q (query)
541# if navigating the revisions that matched a search query539# if navigating the revisions that matched a search query
@@ -553,7 +551,7 @@
553551
554t_context = threading.local()552t_context = threading.local()
555_valid = (553_valid = (
556 'start_revid', 'filter_file_id', 'q', 'remember', 'compare_revid', 'sort')554 'start_revid', 'filter_path', 'q', 'remember', 'compare_revid', 'sort')
557555
558556
559def set_context(map):557def set_context(map):

Subscribers

People subscribed via source and target branches