.+)/',
view_name='browse-revision')
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:
try:
snapshot_context = get_snapshot_context(None, origin_type,
origin_url,
timestamp, visit_id)
except Exception:
raw_rev_url = reverse('browse-revision',
kwargs={'sha1_git': sha1_git})
error_message = \
('The Software Heritage archive has a revision '
'with the hash you provided but the origin '
'mentioned in your request appears broken: %s. '
'Please check the URL and try again.\n\n'
'Nevertheless, you can still browse the revision '
'without origin information: %s'
% (gen_link(origin_url), gen_link(raw_rev_url)))
raise NotFoundExc(error_message)
origin_info = snapshot_context['origin_info']
snapshot_id = snapshot_context['snapshot_id']
elif snapshot_id:
snapshot_context = get_snapshot_context(snapshot_id)
if path:
file_info = \
service.lookup_directory_with_path(revision['directory'], path)
if file_info['type'] == 'dir':
dir_id = file_info['target']
else:
query_string = 'sha1_git:' + file_info['target']
content_data = request_content(query_string,
raise_if_unavailable=False)
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 = {}
author_name = 'None'
revision_data['author'] = 'None'
if revision['author']:
author_name = revision['author']['name'] or \
revision['author']['fullname']
revision_data['author'] = \
gen_person_link(revision['author']['id'], author_name,
snapshot_context)
revision_data['committer'] = 'None'
if revision['committer']:
revision_data['committer'] = \
gen_person_link(revision['committer']['id'],
revision['committer']['name'], snapshot_context)
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 + '
'
revision_data['parents'] = mark_safe(parents)
revision_data['synthetic'] = revision['synthetic']
revision_data['type'] = revision['type']
message_lines = ['None']
if revision['message']:
message_lines = revision['message'].split('\n')
parents_links = '%s parent%s ' % \
(len(revision['parents']),
'' if len(revision['parents']) == 1 else 's')
parents_links += ' '
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': 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
}
swh_objects = [{'type': 'revision',
'id': sha1_git}]
content = None
content_size = None
mimetype = None
language = None
readme_name = None
readme_url = None
readme_html = None
readmes = {}
error_code = 200
error_message = ''
error_description = ''
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(
''
'Raw File')
swh_objects.append({'type': 'content',
'id': file_info['target']})
error_code = content_data['error_code']
error_message = content_data['error_message']
error_description = content_data['error_description']
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)
+ if d['type'] == 'rev':
+ d['url'] = reverse('browse-revision',
+ kwargs={'sha1_git': d['target']})
+ else:
+ 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, readme_html = get_readme_to_display(readmes)
top_right_link = get_revision_log_url(sha1_git, snapshot_context)
top_right_link_text = mark_safe(
''
'History')
vault_cooking['directory_context'] = True
vault_cooking['directory_id'] = dir_id
swh_objects.append({'type': 'directory',
'id': dir_id})
diff_revision_url = reverse('diff-revision', kwargs={'sha1_git': sha1_git},
query_params={'origin_type': origin_type,
'origin': origin_url,
'timestamp': timestamp,
'visit_id': visit_id})
if snapshot_id:
swh_objects.append({'type': 'snapshot',
'id': snapshot_id})
swh_ids = get_swh_persistent_ids(swh_objects, snapshot_context)
heading = 'Revision - %s - %s' %\
(sha1_git[:7], textwrap.shorten(message_lines[0], width=70))
if snapshot_context:
context_found = 'snapshot: %s' % snapshot_context['snapshot_id']
if origin_info:
context_found = 'origin: %s' % origin_info['url']
heading += ' - %s' % context_found
return render(request, 'browse/revision.html',
{'heading': heading,
'swh_object_name': 'Revision',
'swh_object_metadata': revision_data,
'message_header': message_lines[0],
'message_body': '\n'.join(message_lines[1:]),
'parents_links': mark_safe(parents_links),
'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,
'readme_html': readme_html,
'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,
'swh_ids': swh_ids,
'error_code': error_code,
'error_message': error_message,
'error_description': error_description},
status=error_code)
diff --git a/swh/web/browse/views/utils/snapshot_context.py b/swh/web/browse/views/utils/snapshot_context.py
index b2bd72978..8a041f5cc 100644
--- a/swh/web/browse/views/utils/snapshot_context.py
+++ b/swh/web/browse/views/utils/snapshot_context.py
@@ -1,842 +1,846 @@
# 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, 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,
get_swh_persistent_ids
)
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']
if snapshot_context['visit_info']:
timestamp = format_utc_iso_date(snapshot_context['visit_info']['date'],
'%Y-%m-%dT%H:%M:%SZ')
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)
release_id = 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']
release_id = release['id']
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
snapshot_context['release_id'] = release_id
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)
+ if d['type'] == 'rev':
+ d['url'] = reverse('browse-revision',
+ kwargs={'sha1_git': d['target']})
+ else:
+ 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, readme_html = 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
}
swh_objects = [{'type': 'directory',
'id': sha1_git},
{'type': 'revision',
'id': revision_id},
{'type': 'snapshot',
'id': snapshot_id}]
release_id = snapshot_context['release_id']
if release_id:
swh_objects.append({'type': 'release',
'id': release_id})
swh_ids = get_swh_persistent_ids(swh_objects, snapshot_context)
dir_path = '/'.join([bc['name'] for bc in breadcrumbs]) + '/'
context_found = 'snapshot: %s' % snapshot_context['snapshot_id']
if origin_info:
context_found = 'origin: %s' % origin_info['url']
heading = 'Directory - %s - %s - %s' %\
(dir_path, snapshot_context['branch'], context_found)
return render(request, 'browse/directory.html',
{'heading': heading,
'swh_object_name': 'Directory',
'swh_object_metadata': dir_metadata,
'dirs': dirs,
'files': files,
'breadcrumbs': breadcrumbs,
'top_right_link': history_url,
'top_right_link_text': mark_safe(
''
'History'
),
'readme_name': readme_name,
'readme_url': readme_url,
'readme_html': readme_html,
'snapshot_context': snapshot_context,
'vault_cooking': vault_cooking,
'show_actions_menu': True,
'swh_ids': swh_ids})
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,
raise_if_unavailable=False)
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
mimetype = 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']
mimetype = content_display_data['mimetype']
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
cnt_sha1_git = content_data['checksums']['sha1_git']
swh_objects = [{'type': 'content',
'id': cnt_sha1_git},
{'type': 'revision',
'id': revision_id},
{'type': 'snapshot',
'id': snapshot_id}]
release_id = snapshot_context['release_id']
if release_id:
swh_objects.append({'type': 'release',
'id': release_id})
swh_ids = get_swh_persistent_ids(swh_objects, snapshot_context)
content_path = '/'.join([bc['name'] for bc in breadcrumbs])
context_found = 'snapshot: %s' % snapshot_context['snapshot_id']
if origin_info:
context_found = 'origin: %s' % origin_info['url']
heading = 'Content - %s - %s - %s' %\
(content_path, snapshot_context['branch'], context_found)
return render(request, 'browse/content.html',
{'heading': heading,
'swh_object_name': 'Content',
'swh_object_metadata': content_metadata,
'content': content,
'content_size': content_data['length'],
'max_content_size': content_display_max_size,
'mimetype': mimetype,
'language': language,
'breadcrumbs': breadcrumbs,
'top_right_link': content_raw_url,
'top_right_link_text': mark_safe(
''
'Raw File'),
'snapshot_context': snapshot_context,
'vault_cooking': None,
'show_actions_menu': True,
'swh_ids': swh_ids,
'error_code': content_data['error_code'],
'error_message': content_data['error_message'],
'error_description': content_data['error_description']},
status=content_data['error_code'])
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=''
'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
swh_objects = [{'type': 'revision',
'id': revision_id},
{'type': 'snapshot',
'id': snapshot_id}]
release_id = snapshot_context['release_id']
if release_id:
swh_objects.append({'type': 'release',
'id': release_id})
swh_ids = get_swh_persistent_ids(swh_objects, snapshot_context)
context_found = 'snapshot: %s' % snapshot_context['snapshot_id']
if origin_info:
context_found = 'origin: %s' % origin_info['url']
heading = 'Revision history - %s - %s' %\
(snapshot_context['branch'], context_found)
return render(request, 'browse/revision-log.html',
{'heading': heading,
'swh_object_name': 'Revision history',
'swh_object_metadata': revision_metadata,
'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': True,
'swh_ids': swh_ids})
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_type,
'origin': origin_info['url']})
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)
heading = 'Branches - '
if origin_info:
heading += 'origin: %s' % origin_info['url']
else:
heading += 'snapshot: %s' % snapshot_id
return render(request, 'browse/branches.html',
{'heading': heading,
'swh_object_name': 'Branches',
'swh_object_metadata': {},
'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_type,
'origin': origin_info['url']})
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)
heading = 'Releases - '
if origin_info:
heading += 'origin: %s' % origin_info['url']
else:
heading += 'snapshot: %s' % snapshot_id
return render(request, 'browse/releases.html',
{'heading': heading,
'top_panel_visible': False,
'top_panel_collapsible': False,
'swh_object_name': 'Releases',
'swh_object_metadata': {},
'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/data/directory_test_data.py b/swh/web/tests/browse/views/data/directory_test_data.py
index cf0eef76d..eed39c3aa 100644
--- a/swh/web/tests/browse/views/data/directory_test_data.py
+++ b/swh/web/tests/browse/views/data/directory_test_data.py
@@ -1,469 +1,478 @@
# 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
stub_root_directory_sha1 = '08e8329257dad3a3ef7adea48aa6e576cd82de5b'
stub_root_directory_data = \
[
{
"checksums": {
"sha1": "97d7a922a89fdcf4399e8c51555b7f624575310e",
"sha1_git": "7752290577d11e12c8402fa03ee9344d9ed02f8f",
"sha256": "ad98bd676fc2902b8d9ece3c3298d9ec481bd2749aae11ad6d00e8899a6e0c72"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 76,
"name": ".arcconfig",
"perms": 33188,
"status": "visible",
"target": "7752290577d11e12c8402fa03ee9344d9ed02f8f",
"target_url": "/api/1/content/sha1_git:7752290577d11e12c8402fa03ee9344d9ed02f8f/",
"type": "file"
},
{
"checksums": {
"sha1": "745f095b107b91d97dc789d07a2a0b8faaa8700f",
"sha1_git": "8a79cd50ff302720c5543f5cfa9cccad2489f3b8",
"sha256": "279419b197312d2be9fd30f5af3590cfc81d68ddd5ccfccb2f1279fdc355c081"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 155,
"name": ".gitignore",
"perms": 33188,
"status": "visible",
"target": "8a79cd50ff302720c5543f5cfa9cccad2489f3b8",
"target_url": "/api/1/content/sha1_git:8a79cd50ff302720c5543f5cfa9cccad2489f3b8/",
"type": "file"
},
{
"checksums": {
"sha1": "ba15a7a0a3f0742e53966599e65ed8e8935e1139",
"sha1_git": "6365ea05fcd19c6642cb7332ad3e6a0963ae6b0b",
"sha256": "8fc39a39f3950f3a8a98fcb60b9a0b06b0c6df3ee74899cb206b2d50050ebd73"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 59,
"name": ".kateconfig",
"perms": 33188,
"status": "visible",
"target": "6365ea05fcd19c6642cb7332ad3e6a0963ae6b0b",
"target_url": "/api/1/content/sha1_git:6365ea05fcd19c6642cb7332ad3e6a0963ae6b0b/",
"type": "file"
},
{
"checksums": {
"sha1": "ca3eb23cc16b3512763ac286727dd72d78035ecf",
"sha1_git": "5449a540cb927a2cf95072e74c8f53e67dcb061e",
"sha256": "6345d2855ead4ed3f4724408f19d63fb1b7e3492a975568920370dae54d66816"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 241,
"name": ".kateproject",
"perms": 33188,
"status": "visible",
"target": "5449a540cb927a2cf95072e74c8f53e67dcb061e",
"target_url": "/api/1/content/sha1_git:5449a540cb927a2cf95072e74c8f53e67dcb061e/",
"type": "file"
},
{
"checksums": {
"sha1": "ed57cfa75fa0ca475b00920d5338bb4ff51c7114",
"sha1_git": "91c957be760b9c961ccae698fb0e041ef310365c",
"sha256": "df82603f10480d80001e38ae98eb8918a8b9c2cb19e5fb5370ca1d94eff9fb41"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 135,
"name": ".reviewboardrc",
"perms": 33188,
"status": "visible",
"target": "91c957be760b9c961ccae698fb0e041ef310365c",
"target_url": "/api/1/content/sha1_git:91c957be760b9c961ccae698fb0e041ef310365c/",
"type": "file"
},
{
"checksums": {
"sha1": "599e37adf3169c74333ba2378acc23c42270918c",
"sha1_git": "b3b1c238d6ae998d85d3193df1c3c30b722a6d87",
"sha256": "e61b10f1c0685295f5921e86014025ad59a0cad2db972f3300ec141923b56668"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 1482,
"name": "AUTHORS",
"perms": 33188,
"status": "visible",
"target": "b3b1c238d6ae998d85d3193df1c3c30b722a6d87",
"target_url": "/api/1/content/sha1_git:b3b1c238d6ae998d85d3193df1c3c30b722a6d87/",
"type": "file"
},
{
"checksums": {
"sha1": "717cb04728a3c8e3e509368dff6f3898b170af15",
"sha1_git": "3ab996412d61e2e66e6d7ba31d0738cb7fcd6624",
"sha256": "727b93f0a54113559d6984d3a53cc96eb5bb6b9f900422a65d38907dc00798e1"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 2514,
"name": "CMakeLists.txt",
"perms": 33188,
"status": "visible",
"target": "3ab996412d61e2e66e6d7ba31d0738cb7fcd6624",
"target_url": "/api/1/content/sha1_git:3ab996412d61e2e66e6d7ba31d0738cb7fcd6624/",
"type": "file"
},
{
"checksums": {
"sha1": "8624bcdae55baeef00cd11d5dfcfa60f68710a02",
"sha1_git": "94a9ed024d3859793618152ea559a168bbcbb5e2",
"sha256": "8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 35147,
"name": "COPYING-GPL3",
"perms": 33188,
"status": "visible",
"target": "94a9ed024d3859793618152ea559a168bbcbb5e2",
"target_url": "/api/1/content/sha1_git:94a9ed024d3859793618152ea559a168bbcbb5e2/",
"type": "file"
},
{
"checksums": {
"sha1": "f45ee1c765646813b442ca58de72e20a64a7ddba",
"sha1_git": "65c5ca88a67c30becee01c5a8816d964b03862f9",
"sha256": "da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 7651,
"name": "COPYING-LGPL3",
"perms": 33188,
"status": "visible",
"target": "65c5ca88a67c30becee01c5a8816d964b03862f9",
"target_url": "/api/1/content/sha1_git:65c5ca88a67c30becee01c5a8816d964b03862f9/",
"type": "file"
},
{
"checksums": {
"sha1": "e2b9735e3fe7740e377cd085eee521c819a4e736",
"sha1_git": "a96b5730ddd200d0ebec9fae6594a2eca9a1e87e",
"sha256": "c3b824a53fbc4f9a3c7e9046149383b2a39308e430c38ea8d599ed9a3fd5694f"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 25319,
"name": "COPYING.LIB",
"perms": 33188,
"status": "visible",
"target": "a96b5730ddd200d0ebec9fae6594a2eca9a1e87e",
"target_url": "/api/1/content/sha1_git:a96b5730ddd200d0ebec9fae6594a2eca9a1e87e/",
"type": "file"
},
{
"checksums": {
"sha1": "3bb25f251eea54667d43e538365a31acf5d87cce",
"sha1_git": "acd13325a148ad05fa574b458595edb849af6b19",
"sha256": "cbde670dc8f623d61ab28a8b302648cccae22bafc616300cba0fd99c1dae7a94"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 459,
"name": "README.md",
"perms": 33188,
"status": "visible",
"target": "acd13325a148ad05fa574b458595edb849af6b19",
"target_url": "/api/1/content/sha1_git:acd13325a148ad05fa574b458595edb849af6b19/",
"type": "file"
},
{
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 0,
"name": "addons",
"perms": 16384,
"target": "8cd85958b0c15fbf7537219685d3d79185a5d503",
"target_url": "/api/1/directory/8cd85958b0c15fbf7537219685d3d79185a5d503/",
"type": "dir"
},
{
"checksums": {
"sha1": "bdd4876c9d8150f19e520e1517dec705c494b78b",
"sha1_git": "9220caf4063726dc63ceda42a373b2be38a3046d",
"sha256": "78d4776f681c6c246227dcdb002fde2ab2c962ac1f0c70feac37ad2fe6947be7"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 222,
"name": "config.h.cmake",
"perms": 33188,
"status": "visible",
"target": "9220caf4063726dc63ceda42a373b2be38a3046d",
"target_url": "/api/1/content/sha1_git:9220caf4063726dc63ceda42a373b2be38a3046d/",
"type": "file"
},
{
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 0,
"name": "doc",
"perms": 16384,
"target": "4b1bf7180b4c07a103efbcc3e205472ee1ea353b",
"target_url": "/api/1/directory/4b1bf7180b4c07a103efbcc3e205472ee1ea353b/",
"type": "dir"
},
{
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 0,
"name": "kate",
"perms": 16384,
"target": "74e9390431545b89360f75bab447b55fd96137de",
"target_url": "/api/1/directory/74e9390431545b89360f75bab447b55fd96137de/",
"type": "dir"
},
{
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 0,
"name": "kwrite",
"perms": 16384,
"target": "2eb07a97076322bfc1f9408007409f43cbbd4d8c",
"target_url": "/api/1/directory/2eb07a97076322bfc1f9408007409f43cbbd4d8c/",
"type": "dir"
},
{
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 0,
"name": "mac",
"perms": 16384,
"target": "4c3f56a45f23c6cc96d7771b511bc5e3886ec649",
"target_url": "/api/1/directory/4c3f56a45f23c6cc96d7771b511bc5e3886ec649/",
"type": "dir"
},
{
"checksums": {
"sha1": "196915f25d1fcde542515e036fbbdadf47047681",
"sha1_git": "e7195945633a20ff5e64d2556ffc4872a0c4b4dd",
"sha256": "e621462626a86762318d7ad2df0460afb79285c25a78aae1db2a880014e814a5"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 394,
"name": "run-tests-in-xvfb.sh",
"perms": 33261,
"status": "visible",
"target": "e7195945633a20ff5e64d2556ffc4872a0c4b4dd",
"target_url": "/api/1/content/sha1_git:e7195945633a20ff5e64d2556ffc4872a0c4b4dd/",
"type": "file"
},
{
"checksums": {
"sha1": "953d9f0a118652eedb1c46fe95da4f14de54605f",
"sha1_git": "31369dac85e95fdd9439feb6b3fa372efaf48889",
"sha256": "6f3a19457ffbdd6b2d37d7fab6525e7a18f9f315d7ad53b1c050712211d9fd92"
},
"dir_id": "08e8329257dad3a3ef7adea48aa6e576cd82de5b",
"length": 3644,
"name": "urlinfo.h",
"perms": 33188,
"status": "visible",
"target": "31369dac85e95fdd9439feb6b3fa372efaf48889",
"target_url": "/api/1/content/sha1_git:31369dac85e95fdd9439feb6b3fa372efaf48889/",
"type": "file"
}
]
stub_sub_directory_data = \
[
{
"checksums": {
"sha1": "4f322c36a42a51a4ac51cb31059a5e9b62c0b8d6",
"sha1_git": "aa5a37e6a918d30bf0032c6cfba79f1572c293b0",
"sha256": "d3abb3c551e024c420db4f9a309b26b87954c5c73ad903052d079a009e9d7f04"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 3575,
"name": "katesession.cpp",
"perms": 33188,
"status": "visible",
"target": "aa5a37e6a918d30bf0032c6cfba79f1572c293b0",
"target_url": "/api/1/content/sha1_git:aa5a37e6a918d30bf0032c6cfba79f1572c293b0/",
"type": "file"
},
{
"checksums": {
"sha1": "c42547257b0a422f1258074eb453c03269bf353e",
"sha1_git": "cd40bc3e3e61804eca48be777464e194839bc367",
"sha256": "8e460223b074466d121e6d0b3869a8c56d8bf8dd648a7076f8b9707efb3e922f"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 3884,
"name": "katesession.h",
"perms": 33188,
"status": "visible",
"target": "cd40bc3e3e61804eca48be777464e194839bc367",
"target_url": "/api/1/content/sha1_git:cd40bc3e3e61804eca48be777464e194839bc367/",
"type": "file"
},
{
"checksums": {
"sha1": "613e819800af57639942bf18c110b0dbec9cfefe",
"sha1_git": "8e4e46f7d012362488608eb3029f0246d3275d5e",
"sha256": "4f9f6f4fd71b135c03b22d8dd0fec7e7feca2b9257ffc46f55f243a5bf1a707d"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 6473,
"name": "katesessionchooser.cpp",
"perms": 33188,
"status": "visible",
"target": "8e4e46f7d012362488608eb3029f0246d3275d5e",
"target_url": "/api/1/content/sha1_git:8e4e46f7d012362488608eb3029f0246d3275d5e/",
"type": "file"
},
{
"checksums": {
"sha1": "658cb1cce9ae3ea178194763cbfa8213c11bc6c1",
"sha1_git": "c2d1ee22754bd11be7e50668f09571171f449293",
"sha256": "0e65bf00d7e72c9b4131408c0f54f45db4a8945533d52cdb859b617d2c24a2d5"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 1838,
"name": "katesessionchooser.h",
"perms": 33188,
"status": "visible",
"target": "c2d1ee22754bd11be7e50668f09571171f449293",
"target_url": "/api/1/content/sha1_git:c2d1ee22754bd11be7e50668f09571171f449293/",
"type": "file"
},
{
"checksums": {
"sha1": "d2e6159840c9f3aa7774582beb93c6c8de7f6011",
"sha1_git": "5b7ecf823a688a1dc391f2989b556f258b53c92c",
"sha256": "aed0fa5d3d41db5fa4f20a4f3c8cae9cb0ce4b0cbd0a661b931ec457004302fe"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 1370,
"name": "katesessionchooseritem.h",
"perms": 33188,
"status": "visible",
"target": "5b7ecf823a688a1dc391f2989b556f258b53c92c",
"target_url": "/api/1/content/sha1_git:5b7ecf823a688a1dc391f2989b556f258b53c92c/",
"type": "file"
},
{
"checksums": {
"sha1": "2796ed193e91afb5e647934873c3ca2e5f9fd089",
"sha1_git": "a1191a6c9a2170631948c642352629d64d654727",
"sha256": "c18956963dfc6ac66e6de05449020077791fee681056797581edc1b20df37be3"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 5861,
"name": "katesessionmanagedialog.cpp",
"perms": 33188,
"status": "visible",
"target": "a1191a6c9a2170631948c642352629d64d654727",
"target_url": "/api/1/content/sha1_git:a1191a6c9a2170631948c642352629d64d654727/",
"type": "file"
},
{
"checksums": {
"sha1": "4fdc1150cd65ac7502166cb958c5c8422976bd4b",
"sha1_git": "feb31d7bacc40b5d67f858917dfdb05ef9e01aee",
"sha256": "19a7cabf17923fa91d048a2928c4b8b5f04ca6a46c7ce93bfa711c56c8f203d7"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 1838,
"name": "katesessionmanagedialog.h",
"perms": 33188,
"status": "visible",
"target": "feb31d7bacc40b5d67f858917dfdb05ef9e01aee",
"target_url": "/api/1/content/sha1_git:feb31d7bacc40b5d67f858917dfdb05ef9e01aee/",
"type": "file"
},
{
"checksums": {
"sha1": "0e25c6ed7ba157eced5ad16888ff17267077d172",
"sha1_git": "bf3a0b1365de02563fe05ae5f75fc1fb1fbf1d78",
"sha256": "4e4a3f290c042c3cf4fc422666cf3cc97241265c78d96e3af5aecdd27af3962c"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 15676,
"name": "katesessionmanager.cpp",
"perms": 33188,
"status": "visible",
"target": "bf3a0b1365de02563fe05ae5f75fc1fb1fbf1d78",
"target_url": "/api/1/content/sha1_git:bf3a0b1365de02563fe05ae5f75fc1fb1fbf1d78/",
"type": "file"
},
{
"checksums": {
"sha1": "096e52434e8634c827455853f8a9f35ec0c53da3",
"sha1_git": "15a710ebcb65e6399cff38194b19f568cdaf4747",
"sha256": "c0d4dda2ec68aa5b3df966b91a90fb1afedbecf67247cd710b46ede36d8bf36d"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 5622,
"name": "katesessionmanager.h",
"perms": 33188,
"status": "visible",
"target": "15a710ebcb65e6399cff38194b19f568cdaf4747",
"target_url": "/api/1/content/sha1_git:15a710ebcb65e6399cff38194b19f568cdaf4747/",
"type": "file"
},
{
"checksums": {
"sha1": "b7e7f82f27976acf6c04649cbcc703fe8df88ba8",
"sha1_git": "2b43aebeca1dd705fcd3d185c026bbcd13863aab",
"sha256": "bd69ae83132692819edef6925cb75381b0f787f7916fb477a234d6c2968935d7"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 3821,
"name": "katesessionopendialog.cpp",
"perms": 33188,
"status": "visible",
"target": "2b43aebeca1dd705fcd3d185c026bbcd13863aab",
"target_url": "/api/1/content/sha1_git:2b43aebeca1dd705fcd3d185c026bbcd13863aab/",
"type": "file"
},
{
"checksums": {
"sha1": "d20adf1d91c02145dadfc57929ce97382e20f8e5",
"sha1_git": "2377175320886a8de88b7e1ceeb9fd8d4d754274",
"sha256": "666f984226c47b7a2f29b379bf1bebcdd0c881ab8a7c2ef768095fa494763291"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 1599,
"name": "katesessionopendialog.h",
"perms": 33188,
"status": "visible",
"target": "2377175320886a8de88b7e1ceeb9fd8d4d754274",
"target_url": "/api/1/content/sha1_git:2377175320886a8de88b7e1ceeb9fd8d4d754274/",
"type": "file"
},
{
"checksums": {
"sha1": "5609e7a3e71fc685cc78ee472af6313ed9339a89",
"sha1_git": "39253130c5715245cc1c6ce5ecba7a4aec9cbc4c",
"sha256": "372de75c3c0408837c1190714c64c38942b99d3339abe6446651cbf93e7ba486"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 2909,
"name": "katesessionsaction.cpp",
"perms": 33188,
"status": "visible",
"target": "39253130c5715245cc1c6ce5ecba7a4aec9cbc4c",
"target_url": "/api/1/content/sha1_git:39253130c5715245cc1c6ce5ecba7a4aec9cbc4c/",
"type": "file"
},
{
"checksums": {
"sha1": "3b17084f875f847fd85432045b1f39536d55db39",
"sha1_git": "0fd4ea4c765e454ae0cf064192bd7cec7c106cfd",
"sha256": "853deef6938382aef789c36cac4390a59d8eafd65d11fd5ece3ecdaac25515a4"
},
"dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
"length": 1522,
"name": "katesessionsaction.h",
"perms": 33188,
"status": "visible",
"target": "0fd4ea4c765e454ae0cf064192bd7cec7c106cfd",
"target_url": "/api/1/content/sha1_git:0fd4ea4c765e454ae0cf064192bd7cec7c106cfd/",
"type": "file"
+ },
+ {
+ "dir_id": "6cdf1fba5e9559e18242f7aa3fc10e1898c82f32",
+ "length": None,
+ "name": "revision",
+ "perms": 57344,
+ "target": "8750d5607ac066349d60451db1ef211a9cd97515",
+ "target_url": "/api/1/revision/8750d5607ac066349d60451db1ef211a9cd97515/",
+ "type": "rev"
}
]
stub_sub_directory_path = 'kate/session'
diff --git a/swh/web/tests/browse/views/data/origin_test_data.py b/swh/web/tests/browse/views/data/origin_test_data.py
index afc9b69a6..97e33f255 100644
--- a/swh/web/tests/browse/views/data/origin_test_data.py
+++ b/swh/web/tests/browse/views/data/origin_test_data.py
@@ -1,670 +1,684 @@
# 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
origin_info_test_data = {
'id': 2,
'type': 'git',
'url': 'https://github.com/torvalds/linux'
}
origin_visits_test_data = [
{'date': '2015-07-09T21:09:24+00:00',
'metadata': {},
'origin': 2,
'snapshot': '62841f16e8592344b51afc272b98e98108f0b5c5',
'status': 'full',
'visit': 1},
{'date': '2016-02-23T18:05:23.312045+00:00',
'metadata': {},
'origin': 2,
'snapshot': '26befdbf4b393d1e03aa80f2a955bc38b241a8ac',
'status': 'full',
'visit': 2},
{'date': '2016-03-28T01:35:06.554111+00:00',
'metadata': {},
'origin': 2,
'snapshot': 'a07fe7f5bfacf1db47450f04340c7a7b45d3da74',
'status': 'full',
'visit': 3},
{'date': '2016-06-18T01:22:24.808485+00:00',
'metadata': {},
'origin': 2,
'snapshot': 'ce21f317d9fd74bb4af31b06207240031f4b2516',
'status': 'full',
'visit': 4},
{'date': '2016-08-14T12:10:00.536702+00:00',
'metadata': {},
'origin': 2,
'snapshot': 'fe0eac19141fdcdf039e8f5ace5e41b9a2398a49',
'status': 'full',
'visit': 5},
{'date': '2016-08-17T09:16:22.052065+00:00',
'metadata': {},
'origin': 2,
'snapshot': '6903f868df6d94a444818b50becd4835b29be274',
'status': 'full',
'visit': 6},
{'date': '2016-08-29T18:55:54.153721+00:00',
'metadata': {},
'origin': 2,
'snapshot': '6bd66993839dc897aa15a443c4e3b9164f811499',
'status': 'full',
'visit': 7},
{'date': '2016-09-07T08:44:47.861875+00:00',
'metadata': {},
'origin': 2,
'snapshot': 'c06a965f855f4d73c84fbefd859f7df507187d9c',
'status': 'full',
'visit': 8},
{'date': '2016-09-14T10:36:21.505296+00:00',
'metadata': {},
'origin': 2,
'snapshot': '40a5381e2b6c0c04775c5b7e7b37284c3affc129',
'status': 'full',
'visit': 9},
{'date': '2016-09-23T10:14:02.169862+00:00',
'metadata': {},
'origin': 2,
'snapshot': '2252b4d49b9e786eb777a0097a42e51c7193bb9c',
'status': 'full',
'visit': 10}
]
stub_origin_info = {
'id': 7416001,
'type': 'git',
'url': 'https://github.com/webpack/webpack'
}
stub_visit_id = 10
stub_visit_unix_ts = 1493909263
stub_visit_iso_date = '2017-05-04T14:47:43+00:00'
stub_origin_visits = [
{'date': '2015-08-05T18:55:20.899865+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '23fac03bbf6f4d1037bc1477a85bc1c71e586f98',
'visit': 1},
{'date': '2016-03-06T12:16:26.240919+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': 'c71048f1d29a4889ef79f4a64e3c144efe83ea66',
'visit': 2},
{'date': '2016-03-21T11:40:10.329221+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '0d83f0dae76581e55b31ca96d3574261754f1f8f',
'visit': 3},
{'date': '2016-03-29T08:05:17.602649+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': 'eeb186a965a6df47327f34997ee164be66340046',
'visit': 4},
{'date': '2016-07-26T20:11:03.827577+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '1bf4bddbcf9be09ffeeaa68a85b53f039b2d32c2',
'visit': 5},
{'date': '2016-08-13T04:10:22.142897+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '57cfa801c5cba9b034f994c119e122fb153da3ec',
'visit': 6},
{'date': '2016-08-16T22:57:46.201737+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': 'd0c85af82c4c3abb2024c5c628f3e4b584c8b0ef',
'visit': 7},
{'date': '2016-08-17T17:58:43.346437+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '6ba2ff728eed2777156fd5c89424a2a46609f334',
'visit': 8},
{'date': '2016-08-29T23:29:09.445945+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': 'adb6d6adf04454f2b8acd6bf3c89d82dd84c3eed',
'visit': 9},
{'date': '2016-09-07T13:49:15.096109+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '8e29ad8af5f8a9bac86d26f48f956cc0ec69bcd9',
'visit': 10},
{'date': '2016-09-14T15:01:09.017257+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '78fbd0992f12cf1694257b2495e12bd2a3971643',
'visit': 11},
{'date': '2016-09-23T12:29:15.921727+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': '4fa28005f67b46f285bebe7228fe0a96a287ad94',
'visit': 12},
{'date': '2017-02-16T07:44:23.302439+00:00',
'metadata': {},
'origin': 7416001,
'status': 'partial',
'snapshot': None,
'visit': 13},
{'date': '2017-05-04T14:47:43.228455+00:00',
'metadata': {},
'origin': 7416001,
'status': 'full',
'snapshot': 'ea21a9304f34a5b646f81994bd53d580de917427',
'visit': 14}
]
stub_origin_snapshot = (
[
{'directory': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'name': 'HEAD',
'revision': '7bc08e1aa0b08cb23e18715a32aa38517ad34672',
'date': '04 May 2017, 13:27 UTC',
'message': 'Merge pull request #4816 from webpack/bugfix/hoist-immutable-export'},
{'directory': 'c47a824f95109ca7cafdd1c3206332a0d10df55d',
'name': 'refs/heads/0.10',
'revision': 'f944553c77254732c4ce22c0add32aa1f641959d',
'date': '19 June 2013, 12:46 UTC',
'message': 'webpack 0.10'},
{'directory': '45e31184ebb7699cd74175145c7eb11cce3f085e',
'name': 'refs/heads/0.11',
'revision': '0a29109a6e4579926ebc9b03a6301c61861cce62',
'date': '31 December 2013, 12:43 UTC',
'message': '0.11.18'},
{'directory': '42346b33e2d16019490c273ff586ee88817327b3',
'name': 'refs/heads/0.8',
'revision': 'e42701dc6f9b035bfbb5d0fffded905d8b456db4',
'date': 'e42701dc6f9b035bfbb5d0fffded905d8b456db4',
'message': 'fixes #54'},
{'directory': '828c7e9385523f852f8d4dac3cb241e319a9ce61',
'name': 'refs/heads/0.9',
'revision': '6c3f51e6d9491a2463ad099a2ca49255ec83ff00',
'date': '19 March 2013, 07:56 UTC',
'message': 'updated some small things on the cli'},
{'directory': '2c50e78d63bdc4441c8d2691f5729b04f0ab3ecd',
'name': 'refs/heads/1.0',
'revision': 'fb7958d172e1ef6fb77f23bf56818ad24e896e5c',
'date': '03 March 2014, 14:37 UTC',
'message': 'Merge pull request #188 from polotek/patch-1'},
{'directory': '31a3355c4d0a464aa311c5fa11c7f8b20aede6b4',
'name': 'refs/heads/IgnorePluginHotfix',
'revision': 'fdc922a2fa007e71b7ec07252012ffab9a178d4a',
'date': '08 April 2017, 15:50 UTC',
'message': 'add tests for ignored context modules'},
{'directory': 'e566db1fc65cb61b3799c6e0f0ad06b2406f095f',
'name': 'refs/heads/beta',
'revision': '40428853da5d9ce6a8751e13b5e54145337b6a7e',
'date': '04 May 2017, 13:35 UTC',
'message': 'Merge remote-tracking branch \'origin/perf/chunks-set\' into beta'}
],
[{'name': 'v2.1.0-beta.6',
'message': '2.1.0-beta.6',
'date': '22 April 2016, 01:03 UTC',
'id': 'ae2e1a30e4f2ac701e8a6e2fe85a5f200d7e597a',
'target_type': 'revision',
'target': 'ca8b693c2c17bd06778476381fae23b3b21c0475',
'directory': '4e1f9b3c2f5c4bd205051a14af4ade62349ee57a'},
{'name': 'v2.1.0-beta.7',
'message': '2.1.0-beta.7',
'date': '07 May 2016, 00:00 UTC',
'id': '46e94bbdc9e54cf6273a985732446b4c963bf1aa',
'target_type': 'revision',
'target': '9162f9e6eea62137139f95b8aaedee335c870edd',
'directory': '713763f90f17371fec714c1660f229ba41b9f5e2'},
{'name': 'v2.1.0-beta.8',
'message': '2.1.0-beta.8',
'date': '29 May 2016, 20:53 UTC',
'id': '910ada6bf809f8f1c318e098f67f2c0b3c80c888',
'target_type': 'revision',
'target': 'abf0cefd592700a19856c3ef9b6d65f905ec73c1',
'directory': 'd6a069fda992759670851dc38500b2e8dccdc595'},
{'name': 'v2.1.0-beta.9',
'message': '2.1.0-beta.9',
'date': '04 June 2016, 20:19 UTC',
'id': '63063663c86b0c7e5886adbd3c22aacba9b957b0',
'target_type': 'revision',
'target': 'dc3bd055027d8d1ebbb0ebdd07fb73387a0ab6d1',
'directory': '467251807aea6ba83719194e9a1d65e8053f14e0'}
])
stub_origin_master_branch = 'HEAD'
stub_origin_root_directory_sha1 = 'ae59ceecf46367e8e4ad800e231fc76adc3afffb'
stub_origin_root_directory_entries = [
{'checksums': {'sha1': '1a17dd2c8245559b43a90aa7c084572e917effff',
'sha1_git': '012966bd94e648f23b53e71a3f9918e28abc5d81',
'sha256': 'd65ab1f8cdb323e2b568a8e99814b1b986a38beed85a380981b383c0feb93525'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 394,
'name': '.editorconfig',
'perms': 33188,
'status': 'visible',
'target': '012966bd94e648f23b53e71a3f9918e28abc5d81',
'type': 'file'},
{'checksums': {'sha1': '2e727ec452dc592ae6038d3e09cd35d83d7ea265',
'sha1_git': '291a4e25598633cd7c286ad8d6cbe9eee5a6291a',
'sha256': 'd5951c8b796288e0dae1da50575d1b8619462a8df2272cd250146872a1fe804a'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 1839,
'name': '.eslintrc.js',
'perms': 33188,
'status': 'visible',
'target': '291a4e25598633cd7c286ad8d6cbe9eee5a6291a',
'type': 'file'},
{'checksums': {'sha1': '5c59880c0576b2789ec126b61b09fad7a982763b',
'sha1_git': 'ac579eb7bc04ba44fe84f3c8d1082573e9f4f514',
'sha256': '8a59a61ff6c0f568a8f76bab434baf3318c80a75ef6fb1b6eb861a0c97518de0'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 67,
'name': '.gitattributes',
'perms': 33188,
'status': 'visible',
'target': 'ac579eb7bc04ba44fe84f3c8d1082573e9f4f514',
'type': 'file'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': '.github',
'perms': 16384,
'target': '93bdcf98e9c05307b39a9d9e00e48cda6dbd036c',
'type': 'dir'},
{'checksums': {'sha1': '7e1008eee2a373f0db7746d0416856aec6b95c22',
'sha1_git': '84bc35a3abab38bdf87a8f32cc82ce9c136d331e',
'sha256': '7de369f1d26bc34c7b6329de78973db07e341320eace6a8704a65d4c5bf5993f'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 167,
'name': '.gitignore',
'perms': 33188,
'status': 'visible',
'target': '84bc35a3abab38bdf87a8f32cc82ce9c136d331e',
'type': 'file'},
{'checksums': {'sha1': '06d96508b7d343ff42868f9b6406864517935da7',
'sha1_git': '79b049846744a2da3eb1c4ac3b01543f2bdca44a',
'sha256': '697733061d96dd2e061df04dcd86392bb792e2dbe5725a6cb14a436d3c8b76f1'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 706,
'name': '.jsbeautifyrc',
'perms': 33188,
'status': 'visible',
'target': '79b049846744a2da3eb1c4ac3b01543f2bdca44a',
'type': 'file'},
{'checksums': {'sha1': '8041a4a66f46e615c99a850700850a8bd1079dce',
'sha1_git': '90e4f1ef5beb167891b2e029da6eb9b14ab17add',
'sha256': '3d6a76a57351b9e3acc5843ff2127dc2cf70c023133312143f86ee74ba9ef6d3'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 1059,
'name': '.travis.yml',
'perms': 33188,
'status': 'visible',
'target': '90e4f1ef5beb167891b2e029da6eb9b14ab17add',
'type': 'file'},
{'checksums': {'sha1': 'cd52973e43c6f4294e8cdfd3106df602b9993f20',
'sha1_git': 'e5279ebcecd87445648d003c36e6abfebed0ed73',
'sha256': '130672b16dff61b1541b6d26c2e568ac11830a31d04faace1583d3ad4a38720e'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 2058,
'name': 'CONTRIBUTING.md',
'perms': 33188,
'status': 'visible',
'target': 'e5279ebcecd87445648d003c36e6abfebed0ed73',
'type': 'file'},
{'checksums': {'sha1': '3bebb9ba92e45dd02a0512e144f6a46b14a9b8ab',
'sha1_git': '8c11fc7289b75463fe07534fcc8224e333feb7ff',
'sha256': '9068a8782d2fb4c6e432cfa25334efa56f722822180570802bf86e71b6003b1e'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 1071,
'name': 'LICENSE',
'perms': 33188,
'status': 'visible',
'target': '8c11fc7289b75463fe07534fcc8224e333feb7ff',
'type': 'file'},
{'checksums': {'sha1': '6892825420196e84c7104a7ff71ec75db20a1fca',
'sha1_git': '8f96a0a6d3bfe7183765938483585f3981151553',
'sha256': 'b0170cfc28f56ca718b43ab086ca5428f853268687c8c033b4fbf028c66d663e'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 46700,
'name': 'README.md',
'perms': 33188,
'status': 'visible',
'target': '8f96a0a6d3bfe7183765938483585f3981151553',
'type': 'file'},
{'checksums': {'sha1': '9bc4902b282f9f1c9f8f885a6947f3bf0f6e6e5f',
'sha1_git': 'dd6912c8fc97eff255d64da84cfd9837ebf0a05a',
'sha256': 'e06dbc101195ec7ea0b9aa236be4bdc03784a01f64d6e11846ce3a3f6e1080c6'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 590,
'name': 'appveyor.yml',
'perms': 33188,
'status': 'visible',
'target': 'dd6912c8fc97eff255d64da84cfd9837ebf0a05a',
'type': 'file'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'benchmark',
'perms': 16384,
'target': '6bd2996b76e051982aa86499a2b485594e607fe3',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'bin',
'perms': 16384,
'target': '681da97ea1ce9a2bd29e3e72781d80e8b961cd51',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'buildin',
'perms': 16384,
'target': '35cfb25d1b3a4063bf04a43f9cbb7e1e87703708',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'ci',
'perms': 16384,
'target': 'efccd3ce0a0304c8cbcffcfdfcafcf1e598819b8',
'type': 'dir'},
{'checksums': {'sha1': '9eb3d0e3711f68f82d29785e64ebff2c0d7cec7a',
'sha1_git': '1ecf877e445bcf865ef53cfcecadda7e9691aace',
'sha256': '2007e0883c2784bb82584a10d53a0f0c36286dd913741bfd5e4d22b812db529c'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 529,
'name': 'circle.yml',
'perms': 33188,
'status': 'visible',
'target': '1ecf877e445bcf865ef53cfcecadda7e9691aace',
'type': 'file'},
{'checksums': {'sha1': '63209428718e101492c3bb91509f1b4e319b0d7d',
'sha1_git': 'b3fa4e6abe22977e6267e9969a593e790bf2cd36',
'sha256': '5d14c8d70215f46a9722d29c7ebff8cc9bd24509650d7ee601fd461e52a52f7f'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 254,
'name': 'codecov.yml',
'perms': 33188,
'status': 'visible',
'target': 'b3fa4e6abe22977e6267e9969a593e790bf2cd36',
'type': 'file'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'examples',
'perms': 16384,
'target': '7e3ac01795317fbc36a031a9117e7963d6c7da90',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'hot',
'perms': 16384,
'target': 'a5eea6ca952fba9f7ae4177627ed5e22754df9f5',
'type': 'dir'},
{'checksums': {'sha1': '92d9367db4ba049f698f5bf78b6946b8e2d91345',
'sha1_git': 'eaa9cc4a247b01d6a9c0adc91997fefe6a62be1f',
'sha256': 'd4b42fa0651cf3d99dea0ca5bd6ba64cc21e80be7d9ea05b2b4423ef8f16ec36'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 19,
'name': 'input.js',
'perms': 33188,
'status': 'visible',
'target': 'eaa9cc4a247b01d6a9c0adc91997fefe6a62be1f',
'type': 'file'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'lib',
'perms': 16384,
'target': '187d40104aa21475d8af88ccd77fc582cf6ac7a6',
'type': 'dir'},
{'checksums': {'sha1': 'f17ffa2dc14262292e2275efa3730a96fe060c44',
'sha1_git': 'd55b7110929cbba3d94da01494a272b39878ac0f',
'sha256': '012d4446ef8ab6656251b1b7f8e0217a5666ec04ad952e8a617b70946de17166'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 9132,
'name': 'open-bot.yaml',
'perms': 33188,
'status': 'visible',
'target': 'd55b7110929cbba3d94da01494a272b39878ac0f',
'type': 'file'},
{'checksums': {'sha1': '3a6638e72fcc2499f1a4c9b46d4d00d239bbe1c8',
'sha1_git': '6d1aa82c90ecd184d136151eb81d240e1fea723e',
'sha256': '00faf7dde1eb0742f3ca567af4dbcd8c01a38cf30d8faa7f0208f46dbc6b5201'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 4034,
'name': 'package.json',
'perms': 33188,
'status': 'visible',
'target': '6d1aa82c90ecd184d136151eb81d240e1fea723e',
'type': 'file'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'schemas',
'perms': 16384,
'target': 'f1f89c389f73c29e7a5d1a0ce5f9e0f166857815',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'test',
'perms': 16384,
'target': '318c279189d186a1e06653fc5c78c539878c4d7d',
'type': 'dir'},
{'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': None,
'name': 'web_modules',
'perms': 16384,
'target': '93a5cc8e492d0b0323386814a72536381019ef7b',
'type': 'dir'},
{'checksums': {'sha1': '8047389fcc8e286ceed5536c677c2e803032cf84',
'sha1_git': 'eb8509f70158c231a3fd864aecf2649590bbedf3',
'sha256': '8cbe1ce94349ac3bc6cbcc952efd45d838c6b4524af8a773b18e1ebe8b4f936b'},
'dir_id': 'ae59ceecf46367e8e4ad800e231fc76adc3afffb',
'length': 141192,
'name': 'yarn.lock',
'perms': 33188,
'status': 'visible',
'target': 'eb8509f70158c231a3fd864aecf2649590bbedf3',
- 'type': 'file'}
+ 'type': 'file'},
+ {'dir_id': '3b2cbf1a58e7d2848049cf8f1dc1f9ff22415877',
+ 'length': None,
+ 'name': 'revision',
+ 'perms': 57344,
+ 'target': '5da5c4eece39ffb3ae824da433f7e4d004fba217',
+ 'target_url': '/api/1/revision/5da5c4eece39ffb3ae824da433f7e4d004fba217/',
+ 'type': 'rev'},
]
stub_origin_sub_directory_path = 'lib/webworker'
stub_origin_sub_directory_entries = [
{'checksums': {'sha1': '7bf366cd9f4a9835c73aafb70e44f640bab7ad16',
'sha1_git': '870252b7a175ee5ec2edfe2c22b2d56aa04bece4',
'sha256': 'e0af438932627dd9d53b36bfe69c3dbad6dc4d4569f6cdb29d606c9df2b128fa'},
'dir_id': '02b626051e0935ecd28f50337f452db76803f980',
'length': 921,
'name': 'WebWorkerChunkTemplatePlugin.js',
'perms': 33188,
'status': 'visible',
'target': '870252b7a175ee5ec2edfe2c22b2d56aa04bece4',
'type': 'file'},
{'checksums': {'sha1': 'e2862b2787702bd3eb856f73627d5d8df5a8b550',
'sha1_git': 'b3e90d26a68ad9da0a7cc97a262db585fa4c73ba',
'sha256': '1c254e76248ff5ec7e2185cdb1cfd2e0338087244d2d617a868c346317b7646b'},
'dir_id': '02b626051e0935ecd28f50337f452db76803f980',
'length': 1039,
'name': 'WebWorkerHotUpdateChunkTemplatePlugin.js',
'perms': 33188,
'status': 'visible',
'target': 'b3e90d26a68ad9da0a7cc97a262db585fa4c73ba',
'type': 'file'},
{'checksums': {'sha1': 'a1e04061d3e50bb8c024b07e9464da7392f37bf1',
'sha1_git': '1e503e028fdd5322c9f7d8ec50f54006cacf334e',
'sha256': '72dea06510d1a4435346f8dca20d8898a394c52c7382a97bd73d1840e31f90b3'},
'dir_id': '02b626051e0935ecd28f50337f452db76803f980',
'length': 1888,
'name': 'WebWorkerMainTemplate.runtime.js',
'perms': 33188,
'status': 'visible',
'target': '1e503e028fdd5322c9f7d8ec50f54006cacf334e',
'type': 'file'},
{'checksums': {'sha1': 'b95c16e90784cf7025352839133b482149526da0',
'sha1_git': '46c9fe382d606ce19e556deeae6a23af47a8027d',
'sha256': 'c78c7ca9ee0aa341f843a431ef27c75c386607be3037d44ff530bfe3218edb3c'},
'dir_id': '02b626051e0935ecd28f50337f452db76803f980',
'length': 4051,
'name': 'WebWorkerMainTemplatePlugin.js',
'perms': 33188,
'status': 'visible',
'target': '46c9fe382d606ce19e556deeae6a23af47a8027d',
'type': 'file'},
{'checksums': {'sha1': 'ec9df36b1e8dd689d84dbeeeb9f45fe9f9d96605',
'sha1_git': 'd850018bb0d2ad41dd0ae9e5c887dff8a23601e9',
'sha256': 'f995f6a13511955244850c2344c6cef09c10ab24c49f8448544e2b34aa69d03c'},
'dir_id': '02b626051e0935ecd28f50337f452db76803f980',
'length': 763,
'name': 'WebWorkerTemplatePlugin.js',
'perms': 33188,
'status': 'visible',
'target': 'd850018bb0d2ad41dd0ae9e5c887dff8a23601e9',
- 'type': 'file'}
+ 'type': 'file'},
+ {'dir_id': '3b2cbf1a58e7d2848049cf8f1dc1f9ff22415877',
+ 'length': None,
+ 'name': 'revision',
+ 'perms': 57344,
+ 'target': '5da5c4eece39ffb3ae824da433f7e4d004fba217',
+ 'target_url': '/api/1/revision/5da5c4eece39ffb3ae824da433f7e4d004fba217/',
+ 'type': 'rev'}
]
stub_content_origin_info = {
'id': 10357753,
'type': 'git',
'url': 'https://github.com/KDE/kate'
}
stub_content_origin_visit_id = 10
stub_content_origin_visit_unix_ts = 1471457439
stub_content_origin_visit_iso_date = '2016-08-17T18:10:39+00'
stub_content_origin_branch = 'HEAD'
stub_content_origin_visits = [
{'date': '2015-09-26T09:30:52.373449+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': 'bdaf9ac436488a8c6cda927a0f44e172934d3f65',
'status': 'full',
'visit': 1},
{'date': '2016-03-10T05:36:11.118989+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': '2ab1ee17cbaf6fd477832ace039ad85ade748e70',
'status': 'full',
'visit': 2},
{'date': '2016-03-24T07:39:29.727793+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': 'e8f19fe946c251fd69989dabe66a9d1b2cba00f6',
'status': 'full',
'visit': 3},
{'date': '2016-03-31T22:55:31.402863+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': '34a10743dca51484098931a6cf6933582013b458',
'status': 'full',
'visit': 4},
{'date': '2016-05-26T06:25:54.879676+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': 'd8c98ebdf07b2b6542bd74501334b4760b223f9d',
'status': 'full',
'visit': 5},
{'date': '2016-06-07T17:16:33.964164+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': '6d8747764f926c8608be3c37f3fe2e516faf5bf2',
'status': 'full',
'visit': 6},
{'date': '2016-07-27T01:38:20.345358+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': '9fed7618f1b022bcca931c6d29db57b18d843b07',
'status': 'full',
'visit': 7},
{'date': '2016-08-13T04:46:45.987508+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': '4d7cfa75c52152122050914b88ef07a63a8dad9d',
'status': 'full',
'visit': 8},
{'date': '2016-08-16T23:24:13.214496+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': 'bfa9790e0bfad52322acf4d348b97bbc5534db8b',
'status': 'full',
'visit': 9},
{'date': '2016-08-17T18:10:39.841005+00:00',
'metadata': {},
'origin': 10357753,
'snapshot': 'bfa9790e0bfad52322acf4d348b97bbc5534db8b',
'status': 'full',
'visit': 10}
]
stub_content_origin_snapshot = (
[
{'directory': '08e8329257dad3a3ef7adea48aa6e576cd82de5b',
'name': 'HEAD',
'revision': '11f15b0789344427ddf17b8d75f38577c4395ce0',
'date': '02 May 2017, 05:33 UTC',
'message': 'GIT_SILENT made messages (after extraction)'},
{'directory': '2371baf0411e3adf12d65daf86c3b135633dd5e4',
'name': 'refs/heads/Applications/14.12',
'revision': '5b27ad32f8c8da9b6fc898186d59079488fb74c9',
'date': '23 February 2015, 12:10 UTC',
'message': 'SVN_SILENT made messages (.desktop file)'},
{'directory': '5d024d33a218eeb164936301a2f89231d1f0854a',
'name': 'refs/heads/Applications/15.04',
'revision': '4f1e29120795ac643044991e91f24d02c9980202',
'date': '04 July 2015, 12:34 UTC',
'message': 'SVN_SILENT made messages (.desktop file)'},
{'directory': 'f33984df50ec29dbbc86295adb81ebb831e3b86d',
'name': 'refs/heads/Applications/15.08',
'revision': '52722e588f46a32b480b5f304ba21480fc8234b1',
'date': '12 June 2016, 20:28 UTC',
'message': 'Correctly restore view config of all split views'},
{'directory': 'e706b836cf32929a48b6f92c07766f237f9d068f',
'name': 'refs/heads/Applications/15.12',
'revision': '38c4e42c4a653453fc668c704bb8995ae31b5baf',
'date': '06 September 2016, 12:01 UTC',
'message': 'Fix crash in tab switcher plugin when using split views'},
{'directory': 'ebf8ae783b44df5c827bfa46227e5dbe98f25eb4',
'name': 'refs/heads/Applications/16.04',
'revision': 'd0fce3b880ab37a551d75ec940137e0f46bf2143',
'date': '06 September 2016, 12:01 UTC',
'message': 'Fix crash in tab switcher plugin when using split views'}
],
[{'name': 'v4.9.90',
'message': 'KDE 4.9.90',
'date': '09 December 2012, 23:15 UTC',
'id': 'f6a3a31474a86023377ce6fa1cbec3d9ab809d06',
'target_type': 'revision',
'target': '4dd3d7de2f684fcdf27028bafdc022183e33610d',
'directory': 'a5b9c74c35732189b8aa7567f979f9ac36fdb8bc'},
{'name': 'v4.9.95',
'message': 'KDE 4.9.95',
'date': '02 January 2013, 19:00 UTC',
'id': '74bab04b34b243269354f6e5530d6d0edf92f84d',
'target_type': 'revision',
'target': '6bd42579908cf62f094ebca0e100832208967428',
'directory': 'aaeba0a71293465b9026249381c0a1f13a13a43f'},
{'name': 'v4.9.97',
'message': 'KDE 4.9.97',
'date': '05 January 2013, 20:34 UTC',
'id': 'd8bf93d6915c4ab17de882c443423f281c961a1c',
'target_type': 'revision',
'target': '5fbd023fc46ecc57a6772be2aa04f532e8426f43',
'directory': '0ce36caec34ad7c930f35eca907148208b2a3f2b'},
{'name': 'v4.9.98',
'message': 'KDE 4.9.98',
'date': '21 January 2013, 19:36 UTC',
'id': '9bf0265d4fce650926bfd93b117584eb3fd0bd73',
'target_type': 'revision',
'target': '670aff3a940fecf6a085fe71a5bead2edcad8a55',
'directory': '0747fbcc783dfab9e857040287ed400df145079d'}
])
diff --git a/swh/web/tests/browse/views/test_directory.py b/swh/web/tests/browse/views/test_directory.py
index dd7b4dc60..e9479f130 100644
--- a/swh/web/tests/browse/views/test_directory.py
+++ b/swh/web/tests/browse/views/test_directory.py
@@ -1,135 +1,139 @@
# 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 swh.web.common.exc import BadInputExc, NotFoundExc
from swh.web.common.utils import reverse, get_swh_persistent_id
from swh.web.common.utils import gen_path_info
from swh.web.tests.testcase import SWHWebTestCase
from .data.directory_test_data import (
stub_root_directory_sha1, stub_root_directory_data,
stub_sub_directory_path, stub_sub_directory_data
)
class SwhBrowseDirectoryTest(SWHWebTestCase):
@nottest
def directory_view(self, root_directory_sha1, directory_entries,
path=None):
- dirs = [e for e in directory_entries if e['type'] == 'dir']
+ dirs = [e for e in directory_entries if e['type'] in ('dir', 'rev')]
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('browse/directory.html')
self.assertContains(resp, '' +
root_directory_sha1[:7] + '')
self.assertContains(resp, '',
count=len(dirs))
self.assertContains(resp, ' | ',
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})
+ if d['type'] == 'rev':
+ dir_url = reverse('browse-revision',
+ kwargs={'sha1_git': d['target']})
+ else:
+ 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, '',
count=len(path_info)+1)
self.assertContains(resp, '%s' %
(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, '%s' %
(dir_url, p['name']))
self.assertContains(resp, 'vault-cook-directory')
swh_dir_id = get_swh_persistent_id('directory', directory_entries[0]['dir_id']) # noqa
swh_dir_id_url = reverse('browse-swh-id',
kwargs={'swh_id': swh_dir_id})
self.assertContains(resp, swh_dir_id)
self.assertContains(resp, swh_dir_id_url)
@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': stub_sub_directory_data[0]['dir_id'],
'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('browse/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('browse/error.html')
diff --git a/swh/web/tests/browse/views/test_origin.py b/swh/web/tests/browse/views/test_origin.py
index 55dcdda46..e45ca649b 100644
--- a/swh/web/tests/browse/views/test_origin.py
+++ b/swh/web/tests/browse/views/test_origin.py
@@ -1,832 +1,836 @@
# 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.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, get_swh_persistent_id
)
from swh.web.tests.testcase import SWHWebTestCase
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(SWHWebTestCase):
@patch('swh.web.browse.views.origin.get_origin_info')
@patch('swh.web.browse.views.origin.get_origin_visits')
@patch('swh.web.browse.views.origin.service')
@istest
def origin_visits_browse(self, mock_service, mock_get_origin_visits,
mock_get_origin_info):
mock_service.lookup_origin.return_value = origin_info_test_data
mock_get_origin_info.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')
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')
@nottest
def origin_content_view_test(self, origin_info, origin_visits,
origin_branches, origin_releases,
origin_branch,
root_dir_sha1, content_sha1, content_sha1_git,
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, '' % 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, '',
count=len(path_info)+1)
self.assertContains(resp, '%s' %
(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, '%s' %
(dir_url, p['name']))
self.assertContains(resp, '%s' % 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, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '',
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, '' % root_dir_branch_url)
self.assertContains(resp, '',
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, '' % 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')
swh_cnt_id = get_swh_persistent_id('content', content_sha1_git)
swh_cnt_id_url = reverse('browse-swh-id',
kwargs={'swh_id': swh_cnt_id})
self.assertContains(resp, swh_cnt_id)
self.assertContains(resp, swh_cnt_id_url)
@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']
stub_content_text_sha1_git = stub_content_text_data['checksums']['sha1_git']
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_sha1_git,
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_sha1_git,
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_sha1_git,
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_sha1_git,
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']
+ if e['type'] in ('dir', 'rev')]
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, '',
count=len(dirs))
self.assertContains(resp, ' | ',
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)
+ if d['type'] == 'rev':
+ dir_url = reverse('browse-revision',
+ kwargs={'sha1_git': d['target']})
+ else:
+ 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, '', count=nb_bc_paths)
self.assertContains(resp, '%s' %
(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, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args,
query_params=query_params)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
if path:
url_args['path'] = path
self.assertContains(resp, '',
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, '' % root_dir_branch_url)
self.assertContains(resp, '',
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, '' % root_dir_release_url)
self.assertContains(resp, 'vault-cook-directory')
self.assertContains(resp, 'vault-cook-revision')
swh_dir_id = get_swh_persistent_id('directory', directory_entries[0]['dir_id']) # noqa
swh_dir_id_url = reverse('browse-swh-id',
kwargs={'swh_id': swh_dir_id})
self.assertContains(resp, swh_dir_id)
self.assertContains(resp, swh_dir_id_url)
@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_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': stub_origin_sub_directory_entries[0]['dir_id'],
'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 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, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, '',
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, '%s' % (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': origin_info['url']})
self.assertContains(resp, '%s' % (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, 'Branches (%s)' %
(origin_branches_url, len(origin_branches)))
origin_releases_url = \
reverse('browse-origin-releases',
kwargs=url_args)
self.assertContains(resp, 'Releases (%s)' %
(origin_releases_url, len(origin_releases)))
self.assertContains(resp, ' ',
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': origin_info['url']})
self.assertContains(resp, '%s' % (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)
| |