{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/dxr/pulls/comments/31473996","id":31473996,"diff_hunk":"@@ -315,36 +333,104 @@ def sidebar_links(sections):\n               url_for('.parallel', tree=t['name'], path=path),\n               t['description'])\n             for t in frozen_configs()],\n-        'generated_date': frozen['generated_date'],\n+        'generated_date': date,\n         'google_analytics_key': config.google_analytics_key,\n         'filters': filter_menu_items(\n             plugins_named(frozen_config(tree)['enabled_plugins'])),\n-    }\n-\n-    # File template variables\n-    file_vars = {\n+        # File template variables\n         'paths_and_names': _linked_pathname(path, tree),\n         'icon': icon(path),\n         'path': path,\n-        'name': basename(path),\n+        'name': basename(path)\n     }\n \n+\n+def _browse_file(tree, path, line_docs, file_doc, config, date = None, contents = None):\n+    \"\"\"Return a rendered page displaying a source file.\n+\n+    :arg string tree: name of tree on which file is found\n+    :arg string path: relative path from tree root of file\n+    :arg list line_docs: LINE documents as defined in the mapping of core.py,\n+        where the `content` field is dereferenced\n+    :arg file_doc: the FILE document as defined in core.py\n+    :arg config: TreeConfig object of this tree\n+    :arg date: a formatted string representing the generated date, default to now\n+    :arg string contents: the contents of the source file, defaults to joining\n+        the `content` field of all line_docs\n+    \"\"\"\n+    def sidebar_links(sections):\n+        \"\"\"Return data structure to build nav sidebar from. ::\n+\n+            [('Section Name', [{'icon': ..., 'title': ..., 'href': ...}])]\n+\n+        \"\"\"\n+        # Sort by order, resolving ties by section name:\n+        return sorted(sections, key=lambda section: (section['order'],\n+                                                     section['heading']))\n+\n+    if not date:\n+        # Then assume that the file is generated now. Remark: we can't use this\n+        # as the default param because that is only evaluated once, so the same\n+        # time would always be used.\n+        date = datetime.utcnow().strftime(\"%a, %d %b %Y %H:%M:%S +0000\")\n+\n+    common = _build_common_file_template(tree, path, date, config)\n+    links = file_doc.get('links', [])\n     if is_image(path):\n         return render_template(\n             'image_file.html',\n-            **merge(common, file_vars))\n+            **common)\n     else:  # For now, we don't index binary files, so this is always a text one\n+        # We concretize the lines into a list because we iterate over it multiple times\n+        lines = [doc['content'] for doc in line_docs]\n+        if not contents:\n+            # If contents are not provided, we can reconstruct them by\n+            # stitching the lines together.\n+            contents = ''.join(lines)\n+        offsets = cumulative_sum(map(len, lines))\n+        # Construct skimmer objects for all enabled plugins that define a\n+        # file_to_skim class.\n+        skimmers = [plugin.file_to_skim(path, contents, name,\n+                    config.trees[tree], file_doc, line_docs) for name, plugin in\n+                    all_plugins().items() if plugin in","path":"dxr/app.py","position":217,"original_position":217,"commit_id":"1055899526615018f0a3ad03306a432a224385f8","original_commit_id":"1055899526615018f0a3ad03306a432a224385f8","user":{"login":"erikrose","id":295816,"avatar_url":"https://avatars.githubusercontent.com/u/295816?v=3","gravatar_id":"","url":"https://api.github.com/users/erikrose","html_url":"https://github.com/erikrose","followers_url":"https://api.github.com/users/erikrose/followers","following_url":"https://api.github.com/users/erikrose/following{/other_user}","gists_url":"https://api.github.com/users/erikrose/gists{/gist_id}","starred_url":"https://api.github.com/users/erikrose/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/erikrose/subscriptions","organizations_url":"https://api.github.com/users/erikrose/orgs","repos_url":"https://api.github.com/users/erikrose/repos","events_url":"https://api.github.com/users/erikrose/events{/privacy}","received_events_url":"https://api.github.com/users/erikrose/received_events","type":"User","site_admin":false},"body":"items() → iteritems()","created_at":"2015-06-01T21:45:09Z","updated_at":"2015-06-01T21:45:09Z","html_url":"https://github.com/mozilla/dxr/pull/419#discussion_r31473996","pull_request_url":"https://api.github.com/repos/mozilla/dxr/pulls/419","_links":{"self":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/comments/31473996"},"html":{"href":"https://github.com/mozilla/dxr/pull/419#discussion_r31473996"},"pull_request":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/419"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/dxr/pulls/419","id":36243752,"html_url":"https://github.com/mozilla/dxr/pull/419","diff_url":"https://github.com/mozilla/dxr/pull/419.diff","patch_url":"https://github.com/mozilla/dxr/pull/419.patch","issue_url":"https://api.github.com/repos/mozilla/dxr/issues/419","number":419,"state":"open","locked":false,"title":"Refactored VCS, run file skimmers on requests, permalinks","user":{"login":"pelmers","id":2406051,"avatar_url":"https://avatars.githubusercontent.com/u/2406051?v=3","gravatar_id":"","url":"https://api.github.com/users/pelmers","html_url":"https://github.com/pelmers","followers_url":"https://api.github.com/users/pelmers/followers","following_url":"https://api.github.com/users/pelmers/following{/other_user}","gists_url":"https://api.github.com/users/pelmers/gists{/gist_id}","starred_url":"https://api.github.com/users/pelmers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelmers/subscriptions","organizations_url":"https://api.github.com/users/pelmers/orgs","repos_url":"https://api.github.com/users/pelmers/repos","events_url":"https://api.github.com/users/pelmers/events{/privacy}","received_events_url":"https://api.github.com/users/pelmers/received_events","type":"User","site_admin":false},"body":"This work is still a bit rough around the edges, but I wanted to put this up to make it easier to review.\r\n\r\nRelated bugs:\r\n- https://bugzilla.mozilla.org/show_bug.cgi?id=962108\r\n- https://bugzilla.mozilla.org/show_bug.cgi?id=1166397\r\n\r\nSummary of changes:\r\n- Store line endings in ES, and store regions and refs separately. This lets us FileToSkim when files are requested, and merge refs and regions at this point. Increment the format version.\r\n- Add some tests for Git and Mercurial.\r\n- Add permalink button to nav bar along with '/rev' route.\r\n- Add dependence on [hglib](https://pypi.python.org/pypi/python-hglib/) to avoid [MercurialApi](http://mercurial.selenic.com/wiki/MercurialApi)\r\n- Other refactoring and minor fixes.\r\n\r\nStill needed:\r\n- ~~Tests for Perforce.~~ Too expensive.\r\n- ~~Put permalink generation in core.py.~~\r\n- ~~Move link building into vcs.py~~\r\n- ~~Construct some kind of VCS manager for each worker that caches path -> vcs mapping.~~\r\n- ~~Update the docs. Which portions?~~\r\n- ~~Better name than VCSTree ?~~\r\n- Squash some of the back-and-forth commits\r\n- Rename omniglot?\r\n","created_at":"2015-05-26T20:47:07Z","updated_at":"2015-06-01T21:45:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6414576df40a5338c467d585afc94d07d1df8c94","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/dxr/pulls/419/commits","review_comments_url":"https://api.github.com/repos/mozilla/dxr/pulls/419/comments","review_comment_url":"https://api.github.com/repos/mozilla/dxr/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/dxr/issues/419/comments","statuses_url":"https://api.github.com/repos/mozilla/dxr/statuses/1055899526615018f0a3ad03306a432a224385f8","head":{"label":"pelmers:es_permalinks_less_muck","ref":"es_permalinks_less_muck","sha":"1055899526615018f0a3ad03306a432a224385f8","user":{"login":"pelmers","id":2406051,"avatar_url":"https://avatars.githubusercontent.com/u/2406051?v=3","gravatar_id":"","url":"https://api.github.com/users/pelmers","html_url":"https://github.com/pelmers","followers_url":"https://api.github.com/users/pelmers/followers","following_url":"https://api.github.com/users/pelmers/following{/other_user}","gists_url":"https://api.github.com/users/pelmers/gists{/gist_id}","starred_url":"https://api.github.com/users/pelmers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelmers/subscriptions","organizations_url":"https://api.github.com/users/pelmers/orgs","repos_url":"https://api.github.com/users/pelmers/repos","events_url":"https://api.github.com/users/pelmers/events{/privacy}","received_events_url":"https://api.github.com/users/pelmers/received_events","type":"User","site_admin":false},"repo":{"id":15886083,"name":"dxr","full_name":"pelmers/dxr","owner":{"login":"pelmers","id":2406051,"avatar_url":"https://avatars.githubusercontent.com/u/2406051?v=3","gravatar_id":"","url":"https://api.github.com/users/pelmers","html_url":"https://github.com/pelmers","followers_url":"https://api.github.com/users/pelmers/followers","following_url":"https://api.github.com/users/pelmers/following{/other_user}","gists_url":"https://api.github.com/users/pelmers/gists{/gist_id}","starred_url":"https://api.github.com/users/pelmers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelmers/subscriptions","organizations_url":"https://api.github.com/users/pelmers/orgs","repos_url":"https://api.github.com/users/pelmers/repos","events_url":"https://api.github.com/users/pelmers/events{/privacy}","received_events_url":"https://api.github.com/users/pelmers/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pelmers/dxr","description":"An intelligent source code browser","fork":true,"url":"https://api.github.com/repos/pelmers/dxr","forks_url":"https://api.github.com/repos/pelmers/dxr/forks","keys_url":"https://api.github.com/repos/pelmers/dxr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pelmers/dxr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pelmers/dxr/teams","hooks_url":"https://api.github.com/repos/pelmers/dxr/hooks","issue_events_url":"https://api.github.com/repos/pelmers/dxr/issues/events{/number}","events_url":"https://api.github.com/repos/pelmers/dxr/events","assignees_url":"https://api.github.com/repos/pelmers/dxr/assignees{/user}","branches_url":"https://api.github.com/repos/pelmers/dxr/branches{/branch}","tags_url":"https://api.github.com/repos/pelmers/dxr/tags","blobs_url":"https://api.github.com/repos/pelmers/dxr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pelmers/dxr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pelmers/dxr/git/refs{/sha}","trees_url":"https://api.github.com/repos/pelmers/dxr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pelmers/dxr/statuses/{sha}","languages_url":"https://api.github.com/repos/pelmers/dxr/languages","stargazers_url":"https://api.github.com/repos/pelmers/dxr/stargazers","contributors_url":"https://api.github.com/repos/pelmers/dxr/contributors","subscribers_url":"https://api.github.com/repos/pelmers/dxr/subscribers","subscription_url":"https://api.github.com/repos/pelmers/dxr/subscription","commits_url":"https://api.github.com/repos/pelmers/dxr/commits{/sha}","git_commits_url":"https://api.github.com/repos/pelmers/dxr/git/commits{/sha}","comments_url":"https://api.github.com/repos/pelmers/dxr/comments{/number}","issue_comment_url":"https://api.github.com/repos/pelmers/dxr/issues/comments{/number}","contents_url":"https://api.github.com/repos/pelmers/dxr/contents/{+path}","compare_url":"https://api.github.com/repos/pelmers/dxr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pelmers/dxr/merges","archive_url":"https://api.github.com/repos/pelmers/dxr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pelmers/dxr/downloads","issues_url":"https://api.github.com/repos/pelmers/dxr/issues{/number}","pulls_url":"https://api.github.com/repos/pelmers/dxr/pulls{/number}","milestones_url":"https://api.github.com/repos/pelmers/dxr/milestones{/number}","notifications_url":"https://api.github.com/repos/pelmers/dxr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pelmers/dxr/labels{/name}","releases_url":"https://api.github.com/repos/pelmers/dxr/releases{/id}","created_at":"2014-01-13T23:50:59Z","updated_at":"2015-01-02T15:41:27Z","pushed_at":"2015-06-01T21:23:05Z","git_url":"git://github.com/pelmers/dxr.git","ssh_url":"git@github.com:pelmers/dxr.git","clone_url":"https://github.com/pelmers/dxr.git","svn_url":"https://github.com/pelmers/dxr","homepage":"","size":10567,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla:es","ref":"es","sha":"d1398ea9d98a65cf035743f6a0215b2e1c27d878","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":1795049,"name":"dxr","full_name":"mozilla/dxr","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/dxr","description":"An intelligent source code browser","fork":false,"url":"https://api.github.com/repos/mozilla/dxr","forks_url":"https://api.github.com/repos/mozilla/dxr/forks","keys_url":"https://api.github.com/repos/mozilla/dxr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/dxr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/dxr/teams","hooks_url":"https://api.github.com/repos/mozilla/dxr/hooks","issue_events_url":"https://api.github.com/repos/mozilla/dxr/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/dxr/events","assignees_url":"https://api.github.com/repos/mozilla/dxr/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/dxr/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/dxr/tags","blobs_url":"https://api.github.com/repos/mozilla/dxr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/dxr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/dxr/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/dxr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/dxr/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/dxr/languages","stargazers_url":"https://api.github.com/repos/mozilla/dxr/stargazers","contributors_url":"https://api.github.com/repos/mozilla/dxr/contributors","subscribers_url":"https://api.github.com/repos/mozilla/dxr/subscribers","subscription_url":"https://api.github.com/repos/mozilla/dxr/subscription","commits_url":"https://api.github.com/repos/mozilla/dxr/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/dxr/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/dxr/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/dxr/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/dxr/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/dxr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/dxr/merges","archive_url":"https://api.github.com/repos/mozilla/dxr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/dxr/downloads","issues_url":"https://api.github.com/repos/mozilla/dxr/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/dxr/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/dxr/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/dxr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/dxr/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/dxr/releases{/id}","created_at":"2011-05-24T18:52:38Z","updated_at":"2015-05-28T21:33:41Z","pushed_at":"2015-06-01T21:28:52Z","git_url":"git://github.com/mozilla/dxr.git","ssh_url":"git@github.com:mozilla/dxr.git","clone_url":"https://github.com/mozilla/dxr.git","svn_url":"https://github.com/mozilla/dxr","homepage":"https://dxr.readthedocs.org/","size":14770,"stargazers_count":302,"watchers_count":302,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":124,"mirror_url":null,"open_issues_count":29,"forks":124,"open_issues":29,"watchers":302,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/419"},"html":{"href":"https://github.com/mozilla/dxr/pull/419"},"issue":{"href":"https://api.github.com/repos/mozilla/dxr/issues/419"},"comments":{"href":"https://api.github.com/repos/mozilla/dxr/issues/419/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/419/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/dxr/pulls/419/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/dxr/statuses/1055899526615018f0a3ad03306a432a224385f8"}}}}