Page MenuHomeSoftware Heritage

No OneTemporary

diff --git a/swh/web/browse/views/directory.py b/swh/web/browse/views/directory.py
index 2b021a30..2e2b519a 100644
--- a/swh/web/browse/views/directory.py
+++ b/swh/web/browse/views/directory.py
@@ -1,117 +1,125 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
-from django.shortcuts import render
+from django.shortcuts import render, redirect
from django.template.defaultfilters import filesizeformat
from swh.web.common import service
from swh.web.common.utils import reverse, gen_path_info
from swh.web.common.exc import handle_view_exception
from swh.web.browse.utils import (
get_directory_entries, get_snapshot_context,
get_readme_to_display
)
from swh.web.browse.browseurls import browse_route
@browse_route(r'directory/(?P<sha1_git>[0-9a-f]+)/',
r'directory/(?P<sha1_git>[0-9a-f]+)/(?P<path>.+)/',
view_name='browse-directory')
def directory_browse(request, sha1_git, path=None):
"""Django view for browsing the content of a SWH directory identified
by its sha1_git value.
The url that points to it is :http:get:`/browse/directory/(sha1_git)/[(path)/]`
""" # noqa
root_sha1_git = sha1_git
try:
if path:
dir_info = service.lookup_directory_with_path(sha1_git, path)
+ # some readme files can reference assets reachable from the
+ # browsed directory, handle that special case in order to
+ # correctly displayed them
+ if dir_info and dir_info['type'] == 'file':
+ file_raw_url = reverse(
+ 'browse-content-raw',
+ kwargs={'query_string': dir_info['checksums']['sha1']})
+ return redirect(file_raw_url)
sha1_git = dir_info['target']
dirs, files = get_directory_entries(sha1_git)
origin_type = request.GET.get('origin_type', None)
origin_url = request.GET.get('origin_url', None)
if not origin_url:
origin_url = request.GET.get('origin', None)
snapshot_context = None
if origin_url:
snapshot_context = get_snapshot_context(None, origin_type,
origin_url)
if snapshot_context:
snapshot_context['visit_info'] = None
except Exception as exc:
return handle_view_exception(request, exc)
path_info = gen_path_info(path)
breadcrumbs = []
breadcrumbs.append({'name': root_sha1_git[:7],
'url': reverse('browse-directory',
kwargs={'sha1_git': root_sha1_git})})
for pi in path_info:
breadcrumbs.append({'name': pi['name'],
'url': reverse('browse-directory',
kwargs={'sha1_git': root_sha1_git,
'path': pi['path']})})
path = '' if path is None else (path + '/')
for d in dirs:
d['url'] = reverse('browse-directory',
kwargs={'sha1_git': root_sha1_git,
'path': path + d['name']})
sum_file_sizes = 0
readmes = {}
for f in files:
query_string = 'sha1_git:' + f['target']
f['url'] = reverse('browse-content',
kwargs={'query_string': query_string},
query_params={'path': root_sha1_git + '/' +
path + f['name']})
sum_file_sizes += f['length']
f['length'] = filesizeformat(f['length'])
if f['name'].lower().startswith('readme'):
readmes[f['name']] = f['checksums']['sha1']
readme_name, readme_url = get_readme_to_display(readmes)
sum_file_sizes = filesizeformat(sum_file_sizes)
dir_metadata = {'id': sha1_git,
'number of regular files': len(files),
'number of subdirectories': len(dirs),
'sum of regular file sizes': sum_file_sizes}
vault_cooking = {
'directory_context': True,
'directory_id': sha1_git,
'revision_context': False,
'revision_id': None
}
return render(request, 'directory.html',
{'empty_browse': False,
'heading': 'Directory',
'top_panel_visible': True,
'top_panel_collapsible': True,
'top_panel_text': 'Directory metadata',
'swh_object_metadata': dir_metadata,
'main_panel_visible': True,
'dirs': dirs,
'files': files,
'breadcrumbs': breadcrumbs,
'top_right_link': None,
'top_right_link_text': None,
'readme_name': readme_name,
'readme_url': readme_url,
'snapshot_context': snapshot_context,
'vault_cooking': vault_cooking,
'show_actions_menu': True})
diff --git a/swh/web/browse/views/revision.py b/swh/web/browse/views/revision.py
index f11187f7..c5a252e1 100644
--- a/swh/web/browse/views/revision.py
+++ b/swh/web/browse/views/revision.py
@@ -1,464 +1,477 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
import hashlib
import json
from django.http import HttpResponse
-from django.shortcuts import render
+from django.shortcuts import render, redirect
from django.template.defaultfilters import filesizeformat
from django.utils.safestring import mark_safe
from swh.web.common import service
from swh.web.common.utils import reverse, format_utc_iso_date, gen_path_info
from swh.web.common.exc import handle_view_exception
from swh.web.browse.browseurls import browse_route
from swh.web.browse.utils import (
gen_link, gen_person_link, gen_revision_link,
prepare_revision_log_for_display,
get_snapshot_context, gen_snapshot_directory_link,
get_revision_log_url, get_directory_entries,
gen_directory_link, request_content, prepare_content_for_display,
content_display_max_size, gen_snapshot_link, get_readme_to_display
)
def _gen_content_url(revision, query_string, path, snapshot_context):
if snapshot_context:
url_args = snapshot_context['url_args']
url_args['path'] = path
query_params = snapshot_context['query_params']
query_params['revision'] = revision['id']
content_url = reverse('browse-origin-content',
kwargs=url_args,
query_params=query_params)
else:
content_path = '%s/%s' % (revision['directory'], path)
content_url = reverse('browse-content',
kwargs={'query_string': query_string},
query_params={'path': content_path})
return content_url
def _gen_diff_link(idx, diff_anchor, link_text):
if idx < _max_displayed_file_diffs:
return gen_link(diff_anchor, link_text)
else:
return link_text
# TODO: put in conf
_max_displayed_file_diffs = 1000
def _gen_revision_changes_list(revision, changes, snapshot_context):
"""
Returns a HTML string describing the file changes
introduced in a revision.
As this string will be displayed in the browse revision view,
links to adequate file diffs are also generated.
Args:
revision (str): hexadecimal representation of a revision identifier
changes (list): list of file changes in the revision
snapshot_context (dict): optional origin context used to reverse
the content urls
Returns:
A string to insert in a revision HTML view.
"""
changes_msg = []
for i, change in enumerate(changes):
hasher = hashlib.sha1()
from_query_string = ''
to_query_string = ''
diff_id = 'diff-'
if change['from']:
from_query_string = 'sha1_git:' + change['from']['target']
diff_id += change['from']['target'] + '-' + change['from_path']
diff_id += '-'
if change['to']:
to_query_string = 'sha1_git:' + change['to']['target']
diff_id += change['to']['target'] + change['to_path']
change['path'] = change['to_path'] or change['from_path']
url_args = {'from_query_string': from_query_string,
'to_query_string': to_query_string}
query_params = {'path': change['path']}
change['diff_url'] = reverse('diff-contents',
kwargs=url_args,
query_params=query_params)
hasher.update(diff_id.encode('utf-8'))
diff_id = hasher.hexdigest()
change['id'] = diff_id
panel_diff_link = '#panel_' + diff_id
if change['type'] == 'modify':
change['content_url'] = \
_gen_content_url(revision, to_query_string,
change['to_path'], snapshot_context)
changes_msg.append('modified: %s' %
_gen_diff_link(i, panel_diff_link,
change['to_path']))
elif change['type'] == 'insert':
change['content_url'] = \
_gen_content_url(revision, to_query_string,
change['to_path'], snapshot_context)
changes_msg.append('new file: %s' %
_gen_diff_link(i, panel_diff_link,
change['to_path']))
elif change['type'] == 'delete':
parent = service.lookup_revision(revision['parents'][0])
change['content_url'] = \
_gen_content_url(parent,
from_query_string,
change['from_path'], snapshot_context)
changes_msg.append('deleted: %s' %
_gen_diff_link(i, panel_diff_link,
change['from_path']))
elif change['type'] == 'rename':
change['content_url'] = \
_gen_content_url(revision, to_query_string,
change['to_path'], snapshot_context)
link_text = change['from_path'] + ' &rarr; ' + change['to_path']
changes_msg.append('renamed: %s' %
_gen_diff_link(i, panel_diff_link, link_text))
if not changes:
changes_msg.append('No changes')
return mark_safe('\n'.join(changes_msg))
@browse_route(r'revision/(?P<sha1_git>[0-9a-f]+)/diff/',
view_name='diff-revision')
def _revision_diff(request, sha1_git):
"""
Browse internal endpoint to compute revision diff
"""
try:
revision = service.lookup_revision(sha1_git)
snapshot_context = None
origin_type = request.GET.get('origin_type', None)
origin_url = request.GET.get('origin_url', None)
if not origin_url:
origin_url = request.GET.get('origin', None)
timestamp = request.GET.get('timestamp', None)
visit_id = request.GET.get('visit_id', None)
if origin_url:
snapshot_context = get_snapshot_context(None, origin_type,
origin_url,
timestamp, visit_id)
except Exception as exc:
return handle_view_exception(request, exc)
changes = service.diff_revision(sha1_git)
changes_msg = _gen_revision_changes_list(revision, changes,
snapshot_context)
diff_data = {
'total_nb_changes': len(changes),
'changes': changes[:_max_displayed_file_diffs],
'changes_msg': changes_msg
}
diff_data_json = json.dumps(diff_data, separators=(',', ': '))
return HttpResponse(diff_data_json, content_type='application/json')
+NB_LOG_ENTRIES = 20
+
+
+@browse_route(r'revision/(?P<sha1_git>[0-9a-f]+)/log/',
+ view_name='browse-revision-log')
+def revision_log_browse(request, sha1_git):
+ """
+ Django view that produces an HTML display of the history
+ log for a SWH revision identified by its id.
+
+ The url that points to it is :http:get:`/browse/revision/(sha1_git)/log/`.
+ """ # noqa
+ try:
+ per_page = int(request.GET.get('per_page', NB_LOG_ENTRIES))
+ revision_log = service.lookup_revision_log(sha1_git,
+ limit=per_page+1)
+ revision_log = list(revision_log)
+ except Exception as exc:
+ return handle_view_exception(request, exc)
+
+ revs_breadcrumb = request.GET.get('revs_breadcrumb', None)
+
+ revision_log_display_data = prepare_revision_log_for_display(
+ revision_log, per_page, revs_breadcrumb)
+
+ prev_rev = revision_log_display_data['prev_rev']
+ prev_revs_breadcrumb = revision_log_display_data['prev_revs_breadcrumb']
+ prev_log_url = None
+ if prev_rev:
+ prev_log_url = \
+ reverse('browse-revision-log',
+ kwargs={'sha1_git': prev_rev},
+ query_params={'revs_breadcrumb': prev_revs_breadcrumb,
+ 'per_page': per_page})
+
+ next_rev = revision_log_display_data['next_rev']
+ next_revs_breadcrumb = revision_log_display_data['next_revs_breadcrumb']
+ next_log_url = None
+ if next_rev:
+ next_log_url = \
+ reverse('browse-revision-log',
+ kwargs={'sha1_git': next_rev},
+ query_params={'revs_breadcrumb': next_revs_breadcrumb,
+ 'per_page': per_page})
+
+ revision_log_data = revision_log_display_data['revision_log_data']
+
+ for log in revision_log_data:
+ log['directory'] = gen_directory_link(
+ log['directory'],
+ link_text='<i class="fa fa-folder-open fa-fw" aria-hidden="true">'
+ '</i>Browse files',
+ link_attrs={'class': 'btn btn-default btn-sm',
+ 'role': 'button'})
+
+ return render(request, 'revision-log.html',
+ {'empty_browse': False,
+ 'heading': 'Revision history',
+ 'top_panel_visible': False,
+ 'top_panel_collapsible': False,
+ 'top_panel_text': 'Revision history',
+ 'swh_object_metadata': None,
+ 'main_panel_visible': True,
+ 'revision_log': revision_log_data,
+ 'next_log_url': next_log_url,
+ 'prev_log_url': prev_log_url,
+ 'breadcrumbs': None,
+ 'top_right_link': None,
+ 'top_right_link_text': None,
+ 'snapshot_context': None,
+ 'vault_cooking': None,
+ 'show_actions_menu': False})
+
+
@browse_route(r'revision/(?P<sha1_git>[0-9a-f]+)/',
+ r'revision/(?P<sha1_git>[0-9a-f]+)/(?P<extra_path>.+)/',
view_name='browse-revision')
-def revision_browse(request, sha1_git):
+def revision_browse(request, sha1_git, extra_path=None):
"""
Django view that produces an HTML display of a SWH revision
identified by its id.
The url that points to it is :http:get:`/browse/revision/(sha1_git)/`.
"""
try:
revision = service.lookup_revision(sha1_git)
+ # some readme files can reference assets reachable from the
+ # browsed directory, handle that special case in order to
+ # correctly displayed them
+ if extra_path:
+ dir_info = \
+ service.lookup_directory_with_path(revision['directory'],
+ extra_path)
+ if dir_info and dir_info['type'] == 'file':
+ file_raw_url = reverse(
+ 'browse-content-raw',
+ kwargs={'query_string': dir_info['checksums']['sha1']})
+ return redirect(file_raw_url)
origin_info = None
snapshot_context = None
origin_type = request.GET.get('origin_type', None)
origin_url = request.GET.get('origin_url', None)
if not origin_url:
origin_url = request.GET.get('origin', None)
timestamp = request.GET.get('timestamp', None)
visit_id = request.GET.get('visit_id', None)
snapshot_id = request.GET.get('snapshot_id', None)
path = request.GET.get('path', None)
dir_id = None
dirs, files = None, None
content_data = None
if origin_url:
snapshot_context = get_snapshot_context(None, origin_type,
origin_url,
timestamp, visit_id)
origin_info = snapshot_context['origin_info']
snapshot_id = snapshot_context['snapshot_id']
elif snapshot_id:
snapshot_context = get_snapshot_context(snapshot_id)
if path:
path_info = \
service.lookup_directory_with_path(revision['directory'], path)
if path_info['type'] == 'dir':
dir_id = path_info['target']
else:
query_string = 'sha1_git:' + path_info['target']
content_data = request_content(query_string)
else:
dir_id = revision['directory']
if dir_id:
path = '' if path is None else (path + '/')
dirs, files = get_directory_entries(dir_id)
except Exception as exc:
return handle_view_exception(request, exc)
revision_data = {}
revision_data['author'] = gen_person_link(
revision['author']['id'], revision['author']['name'])
revision_data['committer'] = gen_person_link(
revision['committer']['id'], revision['committer']['name'])
revision_data['committer date'] = format_utc_iso_date(
revision['committer_date'])
revision_data['date'] = format_utc_iso_date(revision['date'])
if snapshot_context:
revision_data['snapshot id'] = snapshot_id
revision_data['directory'] = \
gen_snapshot_directory_link(snapshot_context, sha1_git,
link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm', # noqa
'role': 'button'})
else:
revision_data['directory'] = \
gen_directory_link(revision['directory'], link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
revision_data['id'] = sha1_git
revision_data['merge'] = revision['merge']
revision_data['metadata'] = json.dumps(revision['metadata'],
sort_keys=True,
indent=4, separators=(',', ': '))
if origin_info:
revision_data['context-independent revision'] = \
gen_revision_link(sha1_git, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
revision_data['origin id'] = origin_info['id']
revision_data['origin type'] = origin_info['type']
revision_data['origin url'] = gen_link(origin_info['url'],
origin_info['url'])
browse_snapshot_link = \
gen_snapshot_link(snapshot_id, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
revision_data['snapshot'] = browse_snapshot_link
parents = ''
for p in revision['parents']:
parent_link = gen_revision_link(p, snapshot_context=snapshot_context)
parents += parent_link + '<br/>'
revision_data['parents'] = mark_safe(parents)
revision_data['synthetic'] = revision['synthetic']
revision_data['type'] = revision['type']
message_lines = revision['message'].split('\n')
parents_links = '<b>%s parent%s</b> ' % \
(len(revision['parents']),
'' if len(revision['parents']) == 1 else 's')
parents_links += '<i class="octicon octicon-git-commit fa-fw"></i> '
for p in revision['parents']:
parent_link = gen_revision_link(p, shorten_id=True,
snapshot_context=snapshot_context)
parents_links += parent_link
if p != revision['parents'][-1]:
parents_links += ' + '
path_info = gen_path_info(path)
query_params = {'snapshot_id': snapshot_id,
'origin_type': origin_type,
'origin_url': origin_url,
'timestamp': timestamp,
'visit_id': visit_id}
breadcrumbs = []
breadcrumbs.append({'name': revision['directory'][:7],
'url': reverse('browse-revision',
kwargs={'sha1_git': sha1_git},
query_params=query_params)})
for pi in path_info:
query_params['path'] = pi['path']
breadcrumbs.append({'name': pi['name'],
'url': reverse('browse-revision',
kwargs={'sha1_git': sha1_git},
query_params=query_params)})
vault_cooking = {
'directory_context': False,
'directory_id': None,
'revision_context': True,
'revision_id': sha1_git
}
content = None
content_size = None
mimetype = None
language = None
readmes = {}
if content_data:
breadcrumbs[-1]['url'] = None
content_size = content_data['length']
mimetype = content_data['mimetype']
if content_data['raw_data']:
content_display_data = prepare_content_for_display(
content_data['raw_data'], content_data['mimetype'], path)
content = content_display_data['content_data']
language = content_display_data['language']
query_params = {}
if path:
query_params['filename'] = path_info[-1]['name']
top_right_link = reverse('browse-content-raw',
kwargs={'query_string': query_string},
query_params=query_params)
top_right_link_text = mark_safe(
'<i class="fa fa-file-text fa-fw" aria-hidden="true">'
'</i>Raw File')
else:
for d in dirs:
query_params['path'] = path + d['name']
d['url'] = reverse('browse-revision',
kwargs={'sha1_git': sha1_git},
query_params=query_params)
for f in files:
query_params['path'] = path + f['name']
f['url'] = reverse('browse-revision',
kwargs={'sha1_git': sha1_git},
query_params=query_params)
f['length'] = filesizeformat(f['length'])
if f['name'].lower().startswith('readme'):
readmes[f['name']] = f['checksums']['sha1']
readme_name, readme_url = get_readme_to_display(readmes)
top_right_link = get_revision_log_url(sha1_git, snapshot_context)
top_right_link_text = mark_safe(
'<i class="fa fa-history fa-fw" aria-hidden="true"></i>'
'History')
vault_cooking['directory_context'] = True
vault_cooking['directory_id'] = dir_id
diff_revision_url = reverse('diff-revision', kwargs={'sha1_git': sha1_git},
query_params={'origin_type': origin_type,
'origin_url': origin_url,
'timestamp': timestamp,
'visit_id': visit_id})
return render(request, 'revision.html',
{'empty_browse': False,
'heading': 'Revision',
'top_panel_visible': True,
'top_panel_collapsible': True,
'top_panel_text': 'Revision metadata',
'swh_object_metadata': revision_data,
'message_header': message_lines[0],
'message_body': '\n'.join(message_lines[1:]),
'parents_links': mark_safe(parents_links),
'main_panel_visible': True,
'snapshot_context': snapshot_context,
'dirs': dirs,
'files': files,
'content': content,
'content_size': content_size,
'max_content_size': content_display_max_size,
'mimetype': mimetype,
'language': language,
'readme_name': readme_name,
'readme_url': readme_url,
'breadcrumbs': breadcrumbs,
'top_right_link': top_right_link,
'top_right_link_text': top_right_link_text,
'vault_cooking': vault_cooking,
'diff_revision_url': diff_revision_url,
'show_actions_menu': True})
-
-
-NB_LOG_ENTRIES = 20
-
-
-@browse_route(r'revision/(?P<sha1_git>[0-9a-f]+)/log/',
- view_name='browse-revision-log')
-def revision_log_browse(request, sha1_git):
- """
- Django view that produces an HTML display of the history
- log for a SWH revision identified by its id.
-
- The url that points to it is :http:get:`/browse/revision/(sha1_git)/log/`.
- """ # noqa
- try:
- per_page = int(request.GET.get('per_page', NB_LOG_ENTRIES))
- revision_log = service.lookup_revision_log(sha1_git,
- limit=per_page+1)
- revision_log = list(revision_log)
- except Exception as exc:
- return handle_view_exception(request, exc)
-
- revs_breadcrumb = request.GET.get('revs_breadcrumb', None)
-
- revision_log_display_data = prepare_revision_log_for_display(
- revision_log, per_page, revs_breadcrumb)
-
- prev_rev = revision_log_display_data['prev_rev']
- prev_revs_breadcrumb = revision_log_display_data['prev_revs_breadcrumb']
- prev_log_url = None
- if prev_rev:
- prev_log_url = \
- reverse('browse-revision-log',
- kwargs={'sha1_git': prev_rev},
- query_params={'revs_breadcrumb': prev_revs_breadcrumb,
- 'per_page': per_page})
-
- next_rev = revision_log_display_data['next_rev']
- next_revs_breadcrumb = revision_log_display_data['next_revs_breadcrumb']
- next_log_url = None
- if next_rev:
- next_log_url = \
- reverse('browse-revision-log',
- kwargs={'sha1_git': next_rev},
- query_params={'revs_breadcrumb': next_revs_breadcrumb,
- 'per_page': per_page})
-
- revision_log_data = revision_log_display_data['revision_log_data']
-
- for log in revision_log_data:
- log['directory'] = gen_directory_link(
- log['directory'],
- link_text='<i class="fa fa-folder-open fa-fw" aria-hidden="true">'
- '</i>Browse files',
- link_attrs={'class': 'btn btn-default btn-sm',
- 'role': 'button'})
-
- return render(request, 'revision-log.html',
- {'empty_browse': False,
- 'heading': 'Revision history',
- 'top_panel_visible': False,
- 'top_panel_collapsible': False,
- 'top_panel_text': 'Revision history',
- 'swh_object_metadata': None,
- 'main_panel_visible': True,
- 'revision_log': revision_log_data,
- 'next_log_url': next_log_url,
- 'prev_log_url': prev_log_url,
- 'breadcrumbs': None,
- 'top_right_link': None,
- 'top_right_link_text': None,
- 'snapshot_context': None,
- 'vault_cooking': None,
- 'show_actions_menu': False})
diff --git a/swh/web/browse/views/utils/snapshot_context.py b/swh/web/browse/views/utils/snapshot_context.py
index ea24f8cd..85718c7e 100644
--- a/swh/web/browse/views/utils/snapshot_context.py
+++ b/swh/web/browse/views/utils/snapshot_context.py
@@ -1,760 +1,768 @@
# Copyright (C) 2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
# Utility module implementing Django views for browsing the SWH archive
# in a snapshot context.
# Its purpose is to factorize code for the views reachable from the
# /origin/.* and /snapshot/.* endpoints.
-from django.shortcuts import render
+from django.shortcuts import render, redirect
from django.utils.safestring import mark_safe
from django.template.defaultfilters import filesizeformat
from swh.web.browse.utils import (
get_snapshot_context, get_directory_entries, gen_directory_link,
gen_revision_link, request_content, gen_content_link,
prepare_content_for_display, content_display_max_size,
prepare_revision_log_for_display, gen_snapshot_directory_link,
gen_revision_log_link, gen_link, get_readme_to_display
)
from swh.web.common import service
from swh.web.common.exc import (
handle_view_exception, NotFoundExc
)
from swh.web.common.utils import (
reverse, gen_path_info, format_utc_iso_date
)
def _get_branch(branches, branch_name):
"""
Utility function to get a specific branch from a branches list.
Its purpose is to get the default HEAD branch as some SWH origin
(e.g those with svn type) does not have it. In that latter case, check
if there is a master branch instead and returns it.
"""
filtered_branches = \
[b for b in branches if b['name'].endswith(branch_name)]
if len(filtered_branches) > 0:
return filtered_branches[0]
elif branch_name == 'HEAD':
filtered_branches = \
[b for b in branches if b['name'].endswith('master')]
if len(filtered_branches) > 0:
return filtered_branches[0]
elif len(branches) > 0:
return branches[0]
return None
def _get_release(releases, release_name):
"""
Utility function to get a specific release from a releases list.
Returns None if the release can not be found in the list.
"""
filtered_releases = \
[r for r in releases if r['name'] == release_name]
if len(filtered_releases) > 0:
return filtered_releases[0]
else:
return None
def _branch_not_found(branch_type, branch, branches, snapshot_id=None,
origin_info=None, timestamp=None, visit_id=None):
"""
Utility function to raise an exception when a specified branch/release
can not be found.
"""
if branch_type == 'branch':
branch_type = 'Branch'
branch_type_plural = 'branches'
else:
branch_type = 'Release'
branch_type_plural = 'releases'
if snapshot_id and len(branches) == 0:
msg = 'Snapshot with id %s has an empty list' \
' of %s!' % (snapshot_id, branch_type_plural)
elif snapshot_id:
msg = '%s %s for snapshot with id %s' \
' not found!' % (branch_type, branch, snapshot_id)
elif visit_id and len(branches) == 0:
msg = 'Origin with type %s and url %s' \
' for visit with id %s has an empty list' \
' of %s!' % (origin_info['type'], origin_info['url'], visit_id,
branch_type_plural)
elif visit_id:
msg = '%s %s associated to visit with' \
' id %s for origin with type %s and url %s' \
' not found!' % (branch_type, branch, visit_id,
origin_info['type'], origin_info['url'])
elif len(branches) == 0:
msg = 'Origin with type %s and url %s' \
' for visit with timestamp %s has an empty list' \
' of %s!' % (origin_info['type'], origin_info['url'],
timestamp, branch_type_plural)
else:
msg = '%s %s associated to visit with' \
' timestamp %s for origin with type %s' \
' and url %s not found!' % (branch_type, branch, timestamp,
origin_info['type'],
origin_info['url'])
raise NotFoundExc(msg)
def _process_snapshot_request(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None, path=None,
browse_context='directory'):
"""
Utility function to perform common input request processing
for snapshot context views.
"""
visit_id = request.GET.get('visit_id', None)
snapshot_context = get_snapshot_context(snapshot_id, origin_type,
origin_url, timestamp, visit_id)
swh_type = snapshot_context['swh_type']
origin_info = snapshot_context['origin_info']
branches = snapshot_context['branches']
releases = snapshot_context['releases']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
browse_view_name = 'browse-' + swh_type + '-' + browse_context
for b in branches:
branch_url_args = dict(url_args)
branch_query_params = dict(query_params)
branch_query_params['branch'] = b['name']
if path:
b['path'] = path
branch_url_args['path'] = path
b['url'] = reverse(browse_view_name,
kwargs=branch_url_args,
query_params=branch_query_params)
for r in releases:
release_url_args = dict(url_args)
release_query_params = dict(query_params)
release_query_params['release'] = r['name']
if path:
r['path'] = path
release_url_args['path'] = path
r['url'] = reverse(browse_view_name,
kwargs=release_url_args,
query_params=release_query_params)
root_sha1_git = None
revision_id = request.GET.get('revision', None)
release_name = request.GET.get('release', None)
branch_name = None
if revision_id:
revision = service.lookup_revision(revision_id)
root_sha1_git = revision['directory']
branches.append({'name': revision_id,
'revision': revision_id,
'directory': root_sha1_git,
'url': None})
branch_name = revision_id
query_params['revision'] = revision_id
elif release_name:
release = _get_release(releases, release_name)
if release:
root_sha1_git = release['directory']
revision_id = release['target']
query_params['release'] = release_name
else:
_branch_not_found("release", release_name, releases, snapshot_id,
origin_info, timestamp, visit_id)
else:
branch_name = request.GET.get('branch', None)
if branch_name:
query_params['branch'] = branch_name
branch = _get_branch(branches, branch_name or 'HEAD')
if branch:
branch_name = branch['name']
root_sha1_git = branch['directory']
revision_id = branch['revision']
else:
_branch_not_found("branch", branch_name, branches, snapshot_id,
origin_info, timestamp, visit_id)
snapshot_context['query_params'] = query_params
snapshot_context['root_sha1_git'] = root_sha1_git
snapshot_context['revision_id'] = revision_id
snapshot_context['branch'] = branch_name
snapshot_context['release'] = release_name
return snapshot_context
def browse_snapshot_directory(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None, path=None):
"""
Django view implementation for browsing a directory in a snapshot context.
"""
try:
snapshot_context = _process_snapshot_request(request, snapshot_id,
origin_type, origin_url,
timestamp, path,
browse_context='directory') # noqa
root_sha1_git = snapshot_context['root_sha1_git']
sha1_git = root_sha1_git
if path:
dir_info = service.lookup_directory_with_path(root_sha1_git, path)
+ # some readme files can reference assets reachable from the
+ # browsed directory, handle that special case in order to
+ # correctly displayed them
+ if dir_info and dir_info['type'] == 'file':
+ file_raw_url = reverse(
+ 'browse-content-raw',
+ kwargs={'query_string': dir_info['checksums']['sha1']})
+ return redirect(file_raw_url)
sha1_git = dir_info['target']
dirs, files = get_directory_entries(sha1_git)
except Exception as exc:
return handle_view_exception(request, exc)
swh_type = snapshot_context['swh_type']
origin_info = snapshot_context['origin_info']
visit_info = snapshot_context['visit_info']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
revision_id = snapshot_context['revision_id']
snapshot_id = snapshot_context['snapshot_id']
path_info = gen_path_info(path)
browse_view_name = 'browse-' + swh_type + '-directory'
breadcrumbs = []
breadcrumbs.append({'name': root_sha1_git[:7],
'url': reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)})
for pi in path_info:
bc_url_args = dict(url_args)
bc_url_args['path'] = pi['path']
breadcrumbs.append({'name': pi['name'],
'url': reverse(browse_view_name,
kwargs=bc_url_args,
query_params=query_params)})
path = '' if path is None else (path + '/')
for d in dirs:
bc_url_args = dict(url_args)
bc_url_args['path'] = path + d['name']
d['url'] = reverse(browse_view_name,
kwargs=bc_url_args,
query_params=query_params)
sum_file_sizes = 0
readmes = {}
browse_view_name = 'browse-' + swh_type + '-content'
for f in files:
bc_url_args = dict(url_args)
bc_url_args['path'] = path + f['name']
f['url'] = reverse(browse_view_name,
kwargs=bc_url_args,
query_params=query_params)
sum_file_sizes += f['length']
f['length'] = filesizeformat(f['length'])
if f['name'].lower().startswith('readme'):
readmes[f['name']] = f['checksums']['sha1']
readme_name, readme_url = get_readme_to_display(readmes)
browse_view_name = 'browse-' + swh_type + '-log'
history_url = reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)
sum_file_sizes = filesizeformat(sum_file_sizes)
browse_dir_link = \
gen_directory_link(sha1_git, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
browse_rev_link = \
gen_revision_link(revision_id,
snapshot_context=snapshot_context,
link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
dir_metadata = {'id': sha1_git,
'context-independent directory': browse_dir_link,
'number of regular files': len(files),
'number of subdirectories': len(dirs),
'sum of regular file sizes': sum_file_sizes,
'path': '/' + path,
'revision id': revision_id,
'revision': browse_rev_link,
'snapshot id': snapshot_id}
if origin_info:
dir_metadata['origin id'] = origin_info['id']
dir_metadata['origin type'] = origin_info['type']
dir_metadata['origin url'] = origin_info['url']
dir_metadata['origin visit date'] = format_utc_iso_date(visit_info['date']) # noqa
dir_metadata['origin visit id'] = visit_info['visit']
snapshot_context_url = reverse('browse-snapshot-directory',
kwargs={'snapshot_id': snapshot_id},
query_params=request.GET)
browse_snapshot_link = \
gen_link(snapshot_context_url, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
dir_metadata['snapshot context'] = browse_snapshot_link
vault_cooking = {
'directory_context': True,
'directory_id': sha1_git,
'revision_context': True,
'revision_id': revision_id
}
return render(request, 'directory.html',
{'empty_browse': False,
'heading': 'Directory',
'top_panel_visible': True,
'top_panel_collapsible': True,
'top_panel_text': 'Directory metadata',
'swh_object_metadata': dir_metadata,
'main_panel_visible': True,
'dirs': dirs,
'files': files,
'breadcrumbs': breadcrumbs,
'top_right_link': history_url,
'top_right_link_text': mark_safe(
'<i class="fa fa-history fa-fw" aria-hidden="true"></i>'
'History'
),
'readme_name': readme_name,
'readme_url': readme_url,
'snapshot_context': snapshot_context,
'vault_cooking': vault_cooking,
'show_actions_menu': True})
def browse_snapshot_content(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None, path=None):
"""
Django view implementation for browsing a content in a snapshot context.
"""
try:
snapshot_context = _process_snapshot_request(request, snapshot_id,
origin_type, origin_url,
timestamp, path,
browse_context='content')
root_sha1_git = snapshot_context['root_sha1_git']
content_info = service.lookup_directory_with_path(root_sha1_git, path)
sha1_git = content_info['target']
query_string = 'sha1_git:' + sha1_git
content_data = request_content(query_string)
except Exception as exc:
return handle_view_exception(request, exc)
swh_type = snapshot_context['swh_type']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
revision_id = snapshot_context['revision_id']
origin_info = snapshot_context['origin_info']
visit_info = snapshot_context['visit_info']
snapshot_id = snapshot_context['snapshot_id']
content = None
language = None
if content_data['raw_data'] is not None:
content_display_data = prepare_content_for_display(
content_data['raw_data'], content_data['mimetype'], path)
content = content_display_data['content_data']
language = content_display_data['language']
filename = None
path_info = None
browse_view_name = 'browse-' + swh_type + '-directory'
breadcrumbs = []
split_path = path.split('/')
filename = split_path[-1]
path_info = gen_path_info(path[:-len(filename)])
breadcrumbs.append({'name': root_sha1_git[:7],
'url': reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)})
for pi in path_info:
bc_url_args = dict(url_args)
bc_url_args['path'] = pi['path']
breadcrumbs.append({'name': pi['name'],
'url': reverse(browse_view_name,
kwargs=bc_url_args,
query_params=query_params)})
breadcrumbs.append({'name': filename,
'url': None})
browse_content_link = \
gen_content_link(sha1_git, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
content_raw_url = reverse('browse-content-raw',
kwargs={'query_string': query_string},
query_params={'filename': filename})
browse_rev_link = \
gen_revision_link(revision_id,
snapshot_context=snapshot_context,
link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
content_metadata = {
'context-independent content': browse_content_link,
'sha1 checksum': content_data['checksums']['sha1'],
'sha1_git checksum': content_data['checksums']['sha1_git'],
'sha256 checksum': content_data['checksums']['sha256'],
'blake2s256 checksum': content_data['checksums']['blake2s256'],
'mime type': content_data['mimetype'],
'encoding': content_data['encoding'],
'size': filesizeformat(content_data['length']),
'language': content_data['language'],
'licenses': content_data['licenses'],
'path': '/' + path[:-len(filename)],
'filename': filename,
'revision id': revision_id,
'revision': browse_rev_link,
'snapshot id': snapshot_id
}
if origin_info:
content_metadata['origin id'] = origin_info['id']
content_metadata['origin type'] = origin_info['type']
content_metadata['origin url'] = origin_info['url']
content_metadata['origin visit date'] = format_utc_iso_date(visit_info['date']) # noqa
content_metadata['origin visit id'] = visit_info['visit']
browse_snapshot_url = reverse('browse-snapshot-content',
kwargs={'snapshot_id': snapshot_id,
'path': path},
query_params=request.GET)
browse_snapshot_link = \
gen_link(browse_snapshot_url, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
content_metadata['snapshot context'] = browse_snapshot_link
return render(request, 'content.html',
{'empty_browse': False,
'heading': 'Content',
'top_panel_visible': True,
'top_panel_collapsible': True,
'top_panel_text': 'Content metadata',
'swh_object_metadata': content_metadata,
'main_panel_visible': True,
'content': content,
'content_size': content_data['length'],
'max_content_size': content_display_max_size,
'mimetype': content_data['mimetype'],
'language': language,
'breadcrumbs': breadcrumbs,
'top_right_link': content_raw_url,
'top_right_link_text': mark_safe(
'<i class="fa fa-file-text fa-fw" aria-hidden="true">'
'</i>Raw File'),
'snapshot_context': snapshot_context,
'vault_cooking': None,
'show_actions_menu': False})
PER_PAGE = 20
def browse_snapshot_log(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None):
"""
Django view implementation for browsing a revision history in a
snapshot context.
"""
try:
snapshot_context = _process_snapshot_request(request, snapshot_id,
origin_type, origin_url,
timestamp, browse_context='log') # noqa
revision_id = snapshot_context['revision_id']
current_rev = revision_id
per_page = int(request.GET.get('per_page', PER_PAGE))
revs_breadcrumb = request.GET.get('revs_breadcrumb', None)
if revs_breadcrumb:
current_rev = revs_breadcrumb.split('/')[-1]
revision_log = service.lookup_revision_log(current_rev,
limit=per_page+1)
revision_log = list(revision_log)
except Exception as exc:
return handle_view_exception(request, exc)
swh_type = snapshot_context['swh_type']
origin_info = snapshot_context['origin_info']
visit_info = snapshot_context['visit_info']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
snapshot_id = snapshot_context['snapshot_id']
query_params['per_page'] = per_page
revision_log_display_data = prepare_revision_log_for_display(
revision_log, per_page, revs_breadcrumb, snapshot_context)
browse_view_name = 'browse-' + swh_type + '-log'
prev_rev = revision_log_display_data['prev_rev']
prev_revs_breadcrumb = revision_log_display_data['prev_revs_breadcrumb']
prev_log_url = None
query_params['revs_breadcrumb'] = prev_revs_breadcrumb
if prev_rev:
prev_log_url = \
reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)
next_rev = revision_log_display_data['next_rev']
next_revs_breadcrumb = revision_log_display_data['next_revs_breadcrumb']
next_log_url = None
query_params['revs_breadcrumb'] = next_revs_breadcrumb
if next_rev:
next_log_url = \
reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)
revision_log_data = revision_log_display_data['revision_log_data']
for i, log in enumerate(revision_log_data):
params = {
'revision': revision_log[i]['id'],
}
if 'visit_id' in query_params:
params['visit_id'] = query_params['visit_id']
log['directory'] = gen_snapshot_directory_link(
snapshot_context, revision_log[i]['id'],
link_text='<i class="fa fa-folder-open fa-fw" aria-hidden="true">'
'</i>Browse files',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
browse_log_link = \
gen_revision_log_link(revision_id, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
revision_metadata = {
'context-independent revision history': browse_log_link,
'snapshot id': snapshot_id
}
if origin_info:
revision_metadata['origin id'] = origin_info['id']
revision_metadata['origin type'] = origin_info['type']
revision_metadata['origin url'] = origin_info['url']
revision_metadata['origin visit date'] = format_utc_iso_date(visit_info['date']) # noqa
revision_metadata['origin visit id'] = visit_info['visit']
browse_snapshot_url = reverse('browse-snapshot-log',
kwargs={'snapshot_id': snapshot_id},
query_params=request.GET)
browse_snapshot_link = \
gen_link(browse_snapshot_url, link_text='Browse',
link_attrs={'class': 'btn btn-default btn-sm',
'role': 'button'})
revision_metadata['snapshot context'] = browse_snapshot_link
return render(request, 'revision-log.html',
{'empty_browse': False,
'heading': 'Revision history',
'top_panel_visible': True,
'top_panel_collapsible': True,
'top_panel_text': 'Revision history metadata',
'swh_object_metadata': revision_metadata,
'main_panel_visible': True,
'revision_log': revision_log_data,
'next_log_url': next_log_url,
'prev_log_url': prev_log_url,
'breadcrumbs': None,
'top_right_link': None,
'top_right_link_text': None,
'snapshot_context': snapshot_context,
'vault_cooking': None,
'show_actions_menu': False})
def browse_snapshot_branches(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None):
"""
Django view implementation for browsing a list of branches in a snapshot
context.
"""
try:
snapshot_context = _process_snapshot_request(request, snapshot_id,
origin_type, origin_url,
timestamp)
except Exception as exc:
return handle_view_exception(request, exc)
branches_offset = int(request.GET.get('branches_offset', 0))
swh_type = snapshot_context['swh_type']
origin_info = snapshot_context['origin_info']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
browse_view_name = 'browse-' + swh_type + '-directory'
branches = snapshot_context['branches']
displayed_branches = \
branches[branches_offset:branches_offset+PER_PAGE]
for branch in displayed_branches:
if snapshot_id:
revision_url = reverse('browse-revision',
kwargs={'sha1_git': branch['revision']},
query_params={'snapshot_id': snapshot_id})
else:
revision_url = reverse('browse-revision',
kwargs={'sha1_git': branch['revision']},
query_params={'origin_type': origin_info['type'], # noqa
'origin_url': origin_info['url']}) # noqa
query_params['branch'] = branch['name']
directory_url = reverse(browse_view_name,
kwargs=url_args,
query_params=query_params)
del query_params['branch']
branch['revision_url'] = revision_url
branch['directory_url'] = directory_url
browse_view_name = 'browse-' + swh_type + '-branches'
prev_branches_url = None
next_branches_url = None
next_offset = branches_offset + PER_PAGE
prev_offset = branches_offset - PER_PAGE
if next_offset < len(branches):
query_params['branches_offset'] = next_offset
next_branches_url = reverse(browse_view_name,
kwargs=url_args, query_params=query_params)
query_params['branches_offset'] = None
if prev_offset >= 0:
if prev_offset != 0:
query_params['branches_offset'] = prev_offset
prev_branches_url = reverse(browse_view_name,
kwargs=url_args, query_params=query_params)
return render(request, 'branches.html',
{'empty_browse': False,
'heading': 'Origin branches',
'top_panel_visible': False,
'top_panel_collapsible': False,
'top_panel_text': 'Branches list',
'swh_object_metadata': {},
'main_panel_visible': True,
'top_right_link': None,
'top_right_link_text': None,
'displayed_branches': displayed_branches,
'prev_branches_url': prev_branches_url,
'next_branches_url': next_branches_url,
'snapshot_context': snapshot_context})
def browse_snapshot_releases(request, snapshot_id=None, origin_type=None,
origin_url=None, timestamp=None):
"""
Django view implementation for browsing a list of releases in a snapshot
context.
"""
try:
snapshot_context = _process_snapshot_request(request, snapshot_id,
origin_type, origin_url,
timestamp)
except Exception as exc:
return handle_view_exception(request, exc)
releases_offset = int(request.GET.get('releases_offset', 0))
swh_type = snapshot_context['swh_type']
origin_info = snapshot_context['origin_info']
url_args = snapshot_context['url_args']
query_params = snapshot_context['query_params']
releases = snapshot_context['releases']
displayed_releases = \
releases[releases_offset:releases_offset+PER_PAGE]
for release in displayed_releases:
if snapshot_id:
release_url = reverse('browse-release',
kwargs={'sha1_git': release['id']},
query_params={'snapshot_id': snapshot_id})
else:
release_url = reverse('browse-release',
kwargs={'sha1_git': release['id']},
query_params={'origin_type': origin_info['type'], # noqa
'origin_url': origin_info['url']}) # noqa
query_params['release'] = release['name']
del query_params['release']
release['release_url'] = release_url
browse_view_name = 'browse-' + swh_type + '-releases'
prev_releases_url = None
next_releases_url = None
next_offset = releases_offset + PER_PAGE
prev_offset = releases_offset - PER_PAGE
if next_offset < len(releases):
query_params['releases_offset'] = next_offset
next_releases_url = reverse(browse_view_name,
kwargs=url_args, query_params=query_params)
query_params['releases_offset'] = None
if prev_offset >= 0:
if prev_offset != 0:
query_params['releases_offset'] = prev_offset
prev_releases_url = reverse(browse_view_name,
kwargs=url_args, query_params=query_params)
return render(request, 'releases.html',
{'empty_browse': False,
'heading': 'Origin releases',
'top_panel_visible': False,
'top_panel_collapsible': False,
'top_panel_text': 'Releases list',
'swh_object_metadata': {},
'main_panel_visible': True,
'top_right_link': None,
'top_right_link_text': None,
'displayed_releases': displayed_releases,
'prev_releases_url': prev_releases_url,
'next_releases_url': next_releases_url,
'snapshot_context': snapshot_context,
'vault_cooking': None,
'show_actions_menu': False})
diff --git a/swh/web/tests/browse/views/test_directory.py b/swh/web/tests/browse/views/test_directory.py
index 8412ffa6..78595ce7 100644
--- a/swh/web/tests/browse/views/test_directory.py
+++ b/swh/web/tests/browse/views/test_directory.py
@@ -1,130 +1,131 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
from unittest.mock import patch
from nose.tools import istest, nottest
from django.test import TestCase
from swh.web.common.exc import BadInputExc, NotFoundExc
from swh.web.common.utils import reverse
from swh.web.common.utils import gen_path_info
from swh.web.tests.testbase import SWHWebTestBase
from .data.directory_test_data import (
stub_root_directory_sha1, stub_root_directory_data,
stub_sub_directory_path, stub_sub_directory_data
)
class SwhBrowseDirectoryTest(SWHWebTestBase, TestCase):
@nottest
def directory_view(self, root_directory_sha1, directory_entries,
path=None):
dirs = [e for e in directory_entries if e['type'] == 'dir']
files = [e for e in directory_entries if e['type'] == 'file']
url_args = {'sha1_git': root_directory_sha1}
if path:
url_args['path'] = path
url = reverse('browse-directory',
kwargs=url_args)
root_dir_url = reverse('browse-directory',
kwargs={'sha1_git': root_directory_sha1})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('directory.html')
self.assertContains(resp, '<a href="' + root_dir_url + '">' +
root_directory_sha1[:7] + '</a>')
self.assertContains(resp, '<td class="swh-directory">',
count=len(dirs))
self.assertContains(resp, '<td class="swh-content">',
count=len(files))
for d in dirs:
dir_path = d['name']
if path:
dir_path = "%s/%s" % (path, d['name'])
dir_url = reverse('browse-directory',
kwargs={'sha1_git': root_directory_sha1,
'path': dir_path})
self.assertContains(resp, dir_url)
for f in files:
file_path = "%s/%s" % (root_directory_sha1, f['name'])
if path:
file_path = "%s/%s/%s" % (root_directory_sha1, path, f['name'])
query_string = 'sha1_git:' + f['target']
file_url = reverse('browse-content',
kwargs={'query_string': query_string},
query_params={'path': file_path})
self.assertContains(resp, file_url)
path_info = gen_path_info(path)
self.assertContains(resp, '<li class="swh-path">',
count=len(path_info)+1)
self.assertContains(resp, '<a href="%s">%s</a>' %
(root_dir_url, root_directory_sha1[:7]))
for p in path_info:
dir_url = reverse('browse-directory',
kwargs={'sha1_git': root_directory_sha1,
'path': p['path']})
self.assertContains(resp, '<a href="%s">%s</a>' %
(dir_url, p['name']))
self.assertContains(resp, 'vault-cook-directory')
@patch('swh.web.browse.utils.service')
@istest
def root_directory_view(self, mock_service):
mock_service.lookup_directory.return_value = \
stub_root_directory_data
self.directory_view(stub_root_directory_sha1, stub_root_directory_data)
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.directory.service')
@istest
def sub_directory_view(self, mock_directory_service, mock_utils_service):
mock_utils_service.lookup_directory.return_value = \
stub_sub_directory_data
mock_directory_service.lookup_directory_with_path.return_value = \
- {'target': '120c39eeb566c66a77ce0e904d29dfde42228adc'}
+ {'target': '120c39eeb566c66a77ce0e904d29dfde42228adc',
+ 'type': 'dir'}
self.directory_view(stub_root_directory_sha1, stub_sub_directory_data,
stub_sub_directory_path)
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.directory.service')
@istest
def directory_request_errors(self, mock_directory_service,
mock_utils_service):
mock_utils_service.lookup_directory.side_effect = \
BadInputExc('directory not found')
dir_url = reverse('browse-directory',
kwargs={'sha1_git': '1253456'})
resp = self.client.get(dir_url)
self.assertEquals(resp.status_code, 400)
self.assertTemplateUsed('error.html')
mock_utils_service.lookup_directory.side_effect = \
NotFoundExc('directory not found')
dir_url = reverse('browse-directory',
kwargs={'sha1_git': '1253456'})
resp = self.client.get(dir_url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
diff --git a/swh/web/tests/browse/views/test_origin.py b/swh/web/tests/browse/views/test_origin.py
index 3aeffee6..08a1e174 100644
--- a/swh/web/tests/browse/views/test_origin.py
+++ b/swh/web/tests/browse/views/test_origin.py
@@ -1,821 +1,822 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
# flake8: noqa
from unittest.mock import patch
from nose.tools import istest, nottest
from django.test import TestCase
from django.utils.html import escape
from swh.web.common.exc import NotFoundExc
from swh.web.common.utils import (
reverse, gen_path_info, format_utc_iso_date,
parse_timestamp
)
from swh.web.tests.testbase import SWHWebTestBase
from .data.origin_test_data import (
origin_info_test_data,
origin_visits_test_data,
stub_content_origin_info, stub_content_origin_visit_id,
stub_content_origin_visit_unix_ts, stub_content_origin_visit_iso_date,
stub_content_origin_branch,
stub_content_origin_visits, stub_content_origin_snapshot,
stub_origin_info, stub_visit_id,
stub_origin_visits, stub_origin_snapshot,
stub_origin_root_directory_entries, stub_origin_master_branch,
stub_origin_root_directory_sha1, stub_origin_sub_directory_path,
stub_origin_sub_directory_entries, stub_visit_unix_ts, stub_visit_iso_date
)
from .data.content_test_data import (
stub_content_root_dir,
stub_content_text_data,
stub_content_text_path
)
stub_origin_info_no_type = dict(stub_origin_info)
stub_origin_info_no_type['type'] = None
class SwhBrowseOriginTest(SWHWebTestBase, TestCase):
@patch('swh.web.browse.views.origin.get_origin_visits')
@patch('swh.web.browse.views.origin.service')
@istest
def origin_browse(self, mock_service, mock_get_origin_visits):
mock_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_visits.return_value = origin_visits_test_data
url = reverse('browse-origin-visits',
kwargs={'origin_type': origin_info_test_data['type'],
'origin_url': origin_info_test_data['url']})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('origin-visits.html')
self.assertContains(resp, '<pre>%s</pre>' % origin_info_test_data['type'])
self.assertContains(resp, '<pre><a href="%s">%s</a></pre>' %
(origin_info_test_data['url'],
origin_info_test_data['url']))
url = reverse('browse-origin-visits',
kwargs={'origin_url': origin_info_test_data['url']})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('origin-visits.html')
self.assertContains(resp, '<pre>%s</pre>' % origin_info_test_data['type'])
self.assertContains(resp, '<pre><a href="%s">%s</a></pre>' %
(origin_info_test_data['url'],
origin_info_test_data['url']))
@nottest
def origin_content_view_test(self, origin_info, origin_visits,
origin_branches, origin_releases,
origin_branch,
root_dir_sha1, content_sha1,
content_path, content_data,
content_language,
visit_id=None, timestamp=None):
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url'],
'path': content_path}
if not visit_id:
visit_id = origin_visits[-1]['visit']
query_params = {}
if timestamp:
url_args['timestamp'] = timestamp
if visit_id:
query_params['visit_id'] = visit_id
url = reverse('browse-origin-content',
kwargs=url_args,
query_params=query_params)
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('content.html')
self.assertContains(resp, '<code class="%s">' % content_language)
self.assertContains(resp, escape(content_data))
split_path = content_path.split('/')
filename = split_path[-1]
path = content_path.replace(filename, '')[:-1]
path_info = gen_path_info(path)
del url_args['path']
if timestamp:
url_args['timestamp'] = \
format_utc_iso_date(parse_timestamp(timestamp).isoformat(),
'%Y-%m-%dT%H:%M:%S')
root_dir_url = reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<li class="swh-path">',
count=len(path_info)+1)
self.assertContains(resp, '<a href="%s">%s</a>' %
(root_dir_url, root_dir_sha1[:7]))
for p in path_info:
url_args['path'] = p['path']
dir_url = reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">%s</a>' %
(dir_url, p['name']))
self.assertContains(resp, '<li>%s</li>' % filename)
query_string = 'sha1_git:' + content_sha1
url_raw = reverse('browse-content-raw',
kwargs={'query_string': query_string},
query_params={'filename': filename})
self.assertContains(resp, url_raw)
del url_args['path']
origin_branches_url = \
reverse('browse-origin-branches',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">Branches (%s)</a>' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">Releases (%s)</a>' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '<li class="swh-branch">',
count=len(origin_branches))
url_args['path'] = content_path
for branch in origin_branches:
query_params['branch'] = branch['name']
root_dir_branch_url = \
reverse('browse-origin-content',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">' % root_dir_branch_url)
self.assertContains(resp, '<li class="swh-release">',
count=len(origin_releases))
query_params['branch'] = None
for release in origin_releases:
query_params['release'] = release['name']
root_dir_release_url = \
reverse('browse-origin-content',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">' % root_dir_release_url)
del url_args['origin_type']
url = reverse('browse-origin-content',
kwargs=url_args,
query_params=query_params)
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('content.html')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.utils.snapshot_context.request_content')
@istest
def origin_content_view(self, mock_request_content, mock_utils_service,
mock_service, mock_get_origin_visit_snapshot,
mock_get_origin_visits):
stub_content_text_sha1 = stub_content_text_data['checksums']['sha1']
mock_get_origin_visits.return_value = stub_content_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_content_origin_snapshot
mock_service.lookup_directory_with_path.return_value = \
{'target': stub_content_text_sha1}
mock_request_content.return_value = stub_content_text_data
mock_utils_service.lookup_origin.return_value = stub_content_origin_info
self.origin_content_view_test(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp')
self.origin_content_view_test(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
visit_id=stub_content_origin_visit_id)
self.origin_content_view_test(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
timestamp=stub_content_origin_visit_unix_ts)
self.origin_content_view_test(stub_content_origin_info,
stub_content_origin_visits,
stub_content_origin_snapshot[0],
stub_content_origin_snapshot[1],
stub_content_origin_branch,
stub_content_root_dir,
stub_content_text_sha1,
stub_content_text_path,
stub_content_text_data['raw_data'],
'cpp',
timestamp=stub_content_origin_visit_iso_date)
@nottest
def origin_directory_view(self, origin_info, origin_visits,
origin_branches, origin_releases, origin_branch,
root_directory_sha1, directory_entries,
visit_id=None, timestamp=None, path=None):
dirs = [e for e in directory_entries
if e['type'] == 'dir']
files = [e for e in directory_entries
if e['type'] == 'file']
if not visit_id:
visit_id = origin_visits[-1]['visit']
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url']}
query_params = {}
if timestamp:
url_args['timestamp'] = timestamp
else:
query_params['visit_id'] = visit_id
if path:
url_args['path'] = path
url = reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('directory.html')
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('directory.html')
self.assertContains(resp, '<td class="swh-directory">',
count=len(dirs))
self.assertContains(resp, '<td class="swh-content">',
count=len(files))
if timestamp:
url_args['timestamp'] = \
format_utc_iso_date(parse_timestamp(timestamp).isoformat(),
'%Y-%m-%dT%H:%M:%S')
for d in dirs:
dir_path = d['name']
if path:
dir_path = "%s/%s" % (path, d['name'])
dir_url_args = dict(url_args)
dir_url_args['path'] = dir_path
dir_url = reverse('browse-origin-directory',
kwargs=dir_url_args,
query_params=query_params)
self.assertContains(resp, dir_url)
for f in files:
file_path = f['name']
if path:
file_path = "%s/%s" % (path, f['name'])
file_url_args = dict(url_args)
file_url_args['path'] = file_path
file_url = reverse('browse-origin-content',
kwargs=file_url_args,
query_params=query_params)
self.assertContains(resp, file_url)
if 'path' in url_args:
del url_args['path']
root_dir_branch_url = \
reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
nb_bc_paths = 1
if path:
nb_bc_paths = len(path.split('/')) + 1
self.assertContains(resp, '<li class="swh-path">', count=nb_bc_paths)
self.assertContains(resp, '<a href="%s">%s</a>' %
(root_dir_branch_url,
root_directory_sha1[:7]))
origin_branches_url = \
reverse('browse-origin-branches',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">Branches (%s)</a>' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">Releases (%s)</a>' %
(origin_releases_url, len(origin_releases)))
if path:
url_args['path'] = path
self.assertContains(resp, '<li class="swh-branch">',
count=len(origin_branches))
for branch in origin_branches:
query_params['branch'] = branch['name']
root_dir_branch_url = \
reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">' % root_dir_branch_url)
self.assertContains(resp, '<li class="swh-release">',
count=len(origin_releases))
query_params['branch'] = None
for release in origin_releases:
query_params['release'] = release['name']
root_dir_release_url = \
reverse('browse-origin-directory',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, '<a href="%s">' % root_dir_release_url)
self.assertContains(resp, 'vault-cook-directory')
self.assertContains(resp, 'vault-cook-revision')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
@istest
def test_origin_root_directory_view(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_directory.return_value = \
stub_origin_root_directory_entries
mock_utils_service.lookup_origin.return_value = stub_origin_info
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
visit_id=stub_visit_id)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_unix_ts)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_iso_date)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
visit_id=stub_visit_id)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_unix_ts)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_root_directory_entries,
timestamp=stub_visit_iso_date)
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@istest
def origin_sub_directory_view(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_directory.return_value = \
stub_origin_sub_directory_entries
mock_origin_service.lookup_directory_with_path.return_value = \
- {'target': '120c39eeb566c66a77ce0e904d29dfde42228adb'}
+ {'target': '120c39eeb566c66a77ce0e904d29dfde42228adb',
+ 'type' : 'dir'}
mock_utils_service.lookup_origin.return_value = stub_origin_info
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
visit_id=stub_visit_id,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_unix_ts,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_iso_date,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
visit_id=stub_visit_id,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_unix_ts,
path=stub_origin_sub_directory_path)
self.origin_directory_view(stub_origin_info_no_type, stub_origin_visits,
stub_origin_snapshot[0],
stub_origin_snapshot[1],
stub_origin_master_branch,
stub_origin_root_directory_sha1,
stub_origin_sub_directory_entries,
timestamp=stub_visit_iso_date,
path=stub_origin_sub_directory_path)
@patch('swh.web.browse.views.utils.snapshot_context.request_content')
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
@patch('swh.web.browse.views.utils.snapshot_context.service')
@patch('swh.web.browse.views.origin.get_origin_info')
@istest
def test_origin_request_errors(self, mock_get_origin_info,
mock_snapshot_service,
mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits,
mock_request_content):
mock_get_origin_info.side_effect = \
NotFoundExc('origin not found')
url = reverse('browse-origin-visits',
kwargs={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'origin not found', status_code=404)
mock_utils_service.lookup_origin.side_effect = None
mock_utils_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_visits.return_value = []
url = reverse('browse-origin-directory',
kwargs={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, "No SWH visit", status_code=404)
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = \
NotFoundExc('visit not found')
url = reverse('browse-origin-directory',
kwargs={'origin_type': 'foo',
'origin_url': 'bar'},
query_params={'visit_id': len(stub_origin_visits)+1})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'), 'Visit.*not found')
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = None
mock_get_origin_visit_snapshot.return_value = ([], [])
url = reverse('browse-origin-directory',
kwargs={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'),
'Origin.*has an empty list of branches')
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_directory.side_effect = \
NotFoundExc('Directory not found')
url = reverse('browse-origin-directory',
kwargs={'origin_type': 'foo',
'origin_url': 'bar'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Directory not found', status_code=404)
mock_origin_service.lookup_origin.side_effect = None
mock_origin_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_visits.return_value = []
url = reverse('browse-origin-content',
kwargs={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'foo'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, "No SWH visit", status_code=404)
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = \
NotFoundExc('visit not found')
url = reverse('browse-origin-content',
kwargs={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'foo'},
query_params={'visit_id': len(stub_origin_visits)+1})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'), 'Visit.*not found')
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.side_effect = None
mock_get_origin_visit_snapshot.return_value = ([], [])
url = reverse('browse-origin-content',
kwargs={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'baz'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertRegex(resp.content.decode('utf-8'),
'Origin.*has an empty list of branches')
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_snapshot_service.lookup_directory_with_path.return_value = \
{'target': stub_content_text_data['checksums']['sha1']}
mock_request_content.side_effect = \
NotFoundExc('Content not found')
url = reverse('browse-origin-content',
kwargs={'origin_type': 'foo',
'origin_url': 'bar',
'path': 'baz'})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Content not found', status_code=404)
@nottest
def origin_branches_test(self, origin_info, origin_snapshot):
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url']}
url = reverse('browse-origin-branches',
kwargs=url_args)
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('branches.html')
origin_branches = origin_snapshot[0]
origin_releases = origin_snapshot[1]
origin_branches_url = \
reverse('browse-origin-branches',
kwargs=url_args)
self.assertContains(resp, '<a href="%s">Branches (%s)</a>' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args)
self.assertContains(resp, '<a href="%s">Releases (%s)</a>' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '<tr class="swh-origin-branch">',
count=len(origin_branches))
for branch in origin_branches:
browse_branch_url = reverse('browse-origin-directory',
kwargs={'origin_type': origin_info['type'],
'origin_url': origin_info['url']},
query_params={'branch': branch['name']})
self.assertContains(resp, '<a href="%s">%s</a>' % (escape(browse_branch_url), branch['name']))
browse_revision_url = reverse('browse-revision',
kwargs={'sha1_git': branch['revision']},
query_params={'origin_type': origin_info['type'],
'origin_url': origin_info['url']})
self.assertContains(resp, '<a href="%s">%s</a>' % (escape(browse_revision_url), branch['revision'][:7]))
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
@istest
def origin_branches(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_origin.return_value = stub_origin_info
self.origin_branches_test(stub_origin_info, stub_origin_snapshot)
self.origin_branches_test(stub_origin_info_no_type, stub_origin_snapshot)
@nottest
def origin_releases_test(self, origin_info, origin_snapshot):
url_args = {'origin_type': origin_info['type'],
'origin_url': origin_info['url']}
url = reverse('browse-origin-releases',
kwargs=url_args)
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('releases.html')
origin_branches = origin_snapshot[0]
origin_releases = origin_snapshot[1]
origin_branches_url = \
reverse('browse-origin-branches',
kwargs=url_args)
self.assertContains(resp, '<a href="%s">Branches (%s)</a>' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args)
self.assertContains(resp, '<a href="%s">Releases (%s)</a>' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '<tr class="swh-origin-release">',
count=len(origin_releases))
for release in origin_releases:
browse_release_url = reverse('browse-release',
kwargs={'sha1_git': release['id']},
query_params={'origin_type': origin_info['type'],
'origin_url': origin_info['url']})
self.assertContains(resp, '<a href="%s">%s</a>' % (escape(browse_release_url), release['name']))
@patch('swh.web.browse.utils.get_origin_visits')
@patch('swh.web.browse.utils.get_origin_visit_snapshot')
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.origin.service')
@istest
def origin_releases(self, mock_origin_service,
mock_utils_service,
mock_get_origin_visit_snapshot,
mock_get_origin_visits):
mock_get_origin_visits.return_value = stub_origin_visits
mock_get_origin_visit_snapshot.return_value = stub_origin_snapshot
mock_utils_service.lookup_origin.return_value = stub_origin_info
self.origin_releases_test(stub_origin_info, stub_origin_snapshot)
self.origin_releases_test(stub_origin_info_no_type, stub_origin_snapshot)
diff --git a/swh/web/tests/browse/views/test_revision.py b/swh/web/tests/browse/views/test_revision.py
index 0fbaf25e..d7e2e85a 100644
--- a/swh/web/tests/browse/views/test_revision.py
+++ b/swh/web/tests/browse/views/test_revision.py
@@ -1,261 +1,262 @@
# Copyright (C) 2017-2018 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU Affero General Public License version 3, or any later version
# See top-level LICENSE file for more information
# flake8: noqa
from unittest.mock import patch
from nose.tools import istest
from django.test import TestCase
from django.utils.html import escape
from swh.web.common.exc import NotFoundExc
from swh.web.common.utils import reverse, format_utc_iso_date
from swh.web.tests.testbase import SWHWebTestBase
from .data.revision_test_data import (
revision_id_test, revision_metadata_test,
revision_history_log_test
)
from .data.origin_test_data import stub_origin_visits
class SwhBrowseRevisionTest(SWHWebTestBase, TestCase):
@patch('swh.web.browse.views.revision.service')
@patch('swh.web.browse.utils.service')
@istest
def revision_browse(self, mock_service_utils, mock_service):
mock_service.lookup_revision.return_value = revision_metadata_test
url = reverse('browse-revision',
kwargs={'sha1_git': revision_id_test})
author_id = revision_metadata_test['author']['id']
author_name = revision_metadata_test['author']['name']
committer_id = revision_metadata_test['committer']['id']
committer_name = revision_metadata_test['committer']['name']
dir_id = revision_metadata_test['directory']
author_url = reverse('browse-person',
kwargs={'person_id': author_id})
committer_url = reverse('browse-person',
kwargs={'person_id': committer_id})
directory_url = reverse('browse-directory',
kwargs={'sha1_git': dir_id})
history_url = reverse('browse-revision-log',
kwargs={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('revision.html')
self.assertContains(resp, '<a href="%s">%s</a>' %
(author_url, author_name))
self.assertContains(resp, '<a href="%s">%s</a>' %
(committer_url, committer_name))
self.assertContains(resp, directory_url)
self.assertContains(resp, history_url)
for parent in revision_metadata_test['parents']:
parent_url = reverse('browse-revision',
kwargs={'sha1_git': parent})
self.assertContains(resp, '<a href="%s">%s</a>' %
(parent_url, parent))
author_date = revision_metadata_test['date']
committer_date = revision_metadata_test['committer_date']
message_lines = revision_metadata_test['message'].split('\n')
self.assertContains(resp, format_utc_iso_date(author_date))
self.assertContains(resp, format_utc_iso_date(committer_date))
self.assertContains(resp, message_lines[0])
self.assertContains(resp, '\n'.join(message_lines[1:]))
origin_info = {
'id': '7416001',
'type': 'git',
'url': 'https://github.com/webpack/webpack'
}
mock_service_utils.lookup_origin.return_value = origin_info
mock_service_utils.lookup_origin_visits.return_value = stub_origin_visits
mock_service_utils.MAX_LIMIT = 20
origin_directory_url = reverse('browse-origin-directory',
kwargs={'origin_type': origin_info['type'],
'origin_url': origin_info['url']},
query_params={'revision': revision_id_test})
origin_revision_log_url = reverse('browse-origin-log',
kwargs={'origin_type': origin_info['type'],
'origin_url': origin_info['url']},
query_params={'revision': revision_id_test})
url = reverse('browse-revision',
kwargs={'sha1_git': revision_id_test},
query_params={'origin_type': origin_info['type'],
'origin_url': origin_info['url']})
resp = self.client.get(url)
self.assertContains(resp, origin_directory_url)
self.assertContains(resp, origin_revision_log_url)
for parent in revision_metadata_test['parents']:
parent_url = reverse('browse-revision',
kwargs={'sha1_git': parent},
query_params={'origin_type': origin_info['type'],
'origin_url': origin_info['url']})
self.assertContains(resp, '<a href="%s">%s</a>' %
(parent_url, parent))
self.assertContains(resp, 'vault-cook-directory')
self.assertContains(resp, 'vault-cook-revision')
@patch('swh.web.browse.views.revision.service')
@istest
def revision_log_browse(self, mock_service):
per_page = 10
+
mock_service.lookup_revision_log.return_value = \
revision_history_log_test[:per_page+1]
url = reverse('browse-revision-log',
kwargs={'sha1_git': revision_id_test},
query_params={'per_page': per_page})
resp = self.client.get(url)
prev_rev = revision_history_log_test[per_page]['id']
next_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': prev_rev},
query_params={'revs_breadcrumb': revision_id_test,
'per_page': per_page})
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('revision-log.html')
self.assertContains(resp, '<tr class="swh-revision-log-entry">',
count=per_page)
self.assertContains(resp, '<li class="page-item disabled"><a class="page-link">Newer</a></li>')
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Older</a></li>' %
escape(next_page_url))
for log in revision_history_log_test[:per_page]:
author_url = reverse('browse-person',
kwargs={'person_id': log['author']['id']})
revision_url = reverse('browse-revision',
kwargs={'sha1_git': log['id']})
directory_url = reverse('browse-directory',
kwargs={'sha1_git': log['directory']})
self.assertContains(resp, '<a href="%s">%s</a>' %
(author_url, log['author']['name']))
self.assertContains(resp, '<a href="%s">%s</a>' %
(revision_url, log['id'][:7]))
self.assertContains(resp, directory_url)
mock_service.lookup_revision_log.return_value = \
revision_history_log_test[per_page:2*per_page+1]
resp = self.client.get(next_page_url)
prev_prev_rev = revision_history_log_test[2*per_page]['id']
prev_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': revision_id_test},
query_params={'per_page': per_page})
next_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': prev_prev_rev},
query_params={'revs_breadcrumb': revision_id_test + '/' + prev_rev,
'per_page': per_page})
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('revision-log.html')
self.assertContains(resp, '<tr class="swh-revision-log-entry">',
count=per_page)
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Newer</a></li>' %
escape(prev_page_url))
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Older</a></li>' %
escape(next_page_url))
mock_service.lookup_revision_log.return_value = \
revision_history_log_test[2*per_page:3*per_page+1]
resp = self.client.get(next_page_url)
prev_prev_prev_rev = revision_history_log_test[3*per_page]['id']
prev_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': prev_rev},
query_params={'revs_breadcrumb': revision_id_test,
'per_page': per_page})
next_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': prev_prev_prev_rev},
query_params={'revs_breadcrumb': revision_id_test + '/' + prev_rev + '/' + prev_prev_rev,
'per_page': per_page})
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('revision-log.html')
self.assertContains(resp, '<tr class="swh-revision-log-entry">',
count=per_page)
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Newer</a></li>' %
escape(prev_page_url))
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Older</a></li>' %
escape(next_page_url))
mock_service.lookup_revision_log.return_value = \
revision_history_log_test[3*per_page:3*per_page+per_page//2]
resp = self.client.get(next_page_url)
prev_page_url = reverse('browse-revision-log',
kwargs={'sha1_git': prev_prev_rev},
query_params={'revs_breadcrumb': revision_id_test + '/' + prev_rev,
'per_page': per_page})
self.assertEquals(resp.status_code, 200)
self.assertTemplateUsed('revision-log.html')
self.assertContains(resp, '<tr class="swh-revision-log-entry">',
count=per_page//2)
self.assertContains(resp, '<li class="page-item disabled"><a class="page-link">Older</a></li>')
self.assertContains(resp, '<li class="page-item"><a class="page-link" href="%s">Newer</a></li>' %
escape(prev_page_url))
@patch('swh.web.browse.utils.service')
@patch('swh.web.browse.views.revision.service')
@istest
def revision_request_errors(self, mock_service, mock_utils_service):
mock_service.lookup_revision.side_effect = \
NotFoundExc('Revision not found')
url = reverse('browse-revision',
kwargs={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Revision not found', status_code=404)
mock_service.lookup_revision_log.side_effect = \
NotFoundExc('Revision not found')
url = reverse('browse-revision-log',
kwargs={'sha1_git': revision_id_test})
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Revision not found', status_code=404)
url = reverse('browse-revision',
kwargs={'sha1_git': revision_id_test},
query_params={'origin_type': 'git',
'origin_url': 'https://github.com/foo/bar'})
mock_service.lookup_revision.side_effect = None
mock_utils_service.lookup_origin.side_effect = \
NotFoundExc('Origin not found')
resp = self.client.get(url)
self.assertEquals(resp.status_code, 404)
self.assertTemplateUsed('error.html')
self.assertContains(resp, 'Origin not found', status_code=404)

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jul 4, 11:25 AM (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3303314

Event Timeline