Changeset View
Changeset View
Standalone View
Standalone View
swh/web/api/views/revision.py
# Copyright (C) 2015-2018 The Software Heritage developers | # Copyright (C) 2015-2018 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU Affero General Public License version 3, or any later version | # License: GNU Affero General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
from django.http import HttpResponse | from django.http import HttpResponse | ||||
from swh.web.common import service | from swh.web.common import service | ||||
from swh.web.common.utils import reverse | from swh.web.common.utils import reverse | ||||
from swh.web.common.utils import parse_timestamp | |||||
from swh.web.api import utils | from swh.web.api import utils | ||||
from swh.web.api.apidoc import api_doc | from swh.web.api.apidoc import api_doc | ||||
from swh.web.api.apiurls import api_route | from swh.web.api.apiurls import api_route | ||||
from swh.web.api.views.utils import api_lookup | from swh.web.api.views.utils import api_lookup | ||||
def _revision_directory_by(revision, path, request_path, | def _revision_directory_by(revision, path, request_path, | ||||
limit=100, with_data=False): | limit=100, with_data=False): | ||||
Show All 21 Lines | def _revision_directory_by(revision, path, request_path, | ||||
if result['type'] == 'dir': # dir_entries | if result['type'] == 'dir': # dir_entries | ||||
result['content'] = list(map(enrich_directory_local, content)) | result['content'] = list(map(enrich_directory_local, content)) | ||||
else: # content | else: # content | ||||
result['content'] = utils.enrich_content(content) | result['content'] = utils.enrich_content(content) | ||||
return result | return result | ||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/log/', | |||||
'api-revision-origin-log') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)/log/', | |||||
'api-revision-origin-log') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/ts/(?P<ts>.+)/log/', | |||||
'api-revision-origin-log') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)' | |||||
r'/ts/(?P<ts>.+)/log/', | |||||
'api-revision-origin-log') | |||||
@api_doc('/revision/origin/log/') | |||||
def api_revision_log_by(request, origin_id, | |||||
branch_name='refs/heads/master', | |||||
ts=None): | |||||
""" | |||||
.. http:get:: /api/1/revision/origin/(origin_id)[/branch/(branch_name)][/ts/(timestamp)]/log | |||||
Show the commit log for a revision, searching for it based on software origin, | |||||
branch name, and/or visit timestamp. | |||||
This endpoint behaves like :http:get:`/api/1/revision/(sha1_git)[/prev/(prev_sha1s)]/log/`, | |||||
but operates on the revision that has been found at a given software origin, | |||||
close to a given point in time, pointed by a given branch. | |||||
:param int origin_id: a software origin identifier | |||||
:param string branch_name: optional parameter specifying a fully-qualified branch name | |||||
associated to the software origin, e.g., "refs/heads/master". Defaults to the master branch. | |||||
:param string timestamp: optional parameter specifying a timestamp close to which the revision | |||||
pointed by the given branch should be looked up. The timestamp can be expressed either | |||||
as an ISO date or as a Unix one (in UTC). Defaults to now. | |||||
:reqheader Accept: the requested response content type, | |||||
either ``application/json`` (default) or ``application/yaml`` | |||||
:resheader Content-Type: this depends on :http:header:`Accept` header of request | |||||
:>jsonarr object author: information about the author of the revision | |||||
:>jsonarr string author_url: link to :http:get:`/api/1/person/(person_id)/` to get | |||||
information about the author of the revision | |||||
:>jsonarr object committer: information about the committer of the revision | |||||
:>jsonarr string committer_url: link to :http:get:`/api/1/person/(person_id)/` to get | |||||
information about the committer of the revision | |||||
:>jsonarr string committer_date: ISO representation of the commit date (in UTC) | |||||
:>jsonarr string date: ISO representation of the revision date (in UTC) | |||||
:>jsonarr string directory: the unique identifier that revision points to | |||||
:>jsonarr string directory_url: link to :http:get:`/api/1/directory/(sha1_git)/[(path)/]` | |||||
to get information about the directory associated to the revision | |||||
:>jsonarr string id: the revision unique identifier | |||||
:>jsonarr boolean merge: whether or not the revision corresponds to a merge commit | |||||
:>jsonarr string message: the message associated to the revision | |||||
:>jsonarr array parents: the parents of the revision, i.e. the previous revisions | |||||
that head directly to it, each entry of that array contains an unique parent | |||||
revision identifier but also a link to :http:get:`/api/1/revision/(sha1_git)/` | |||||
to get more information about it | |||||
:>jsonarr string type: the type of the revision | |||||
**Allowed HTTP Methods:** :http:method:`get`, :http:method:`head`, :http:method:`options` | |||||
:statuscode 200: no error | |||||
:statuscode 404: no revision matching the given criteria could be found in the archive | |||||
**Example:** | |||||
.. parsed-literal:: | |||||
:swh_web_api:`revision/origin/723566/ts/2016-01-17T00:00:00+00:00/log/` | |||||
""" # noqa | |||||
result = {} | |||||
per_page = int(request.query_params.get('per_page', '10')) | |||||
if ts: | |||||
ts = parse_timestamp(ts) | |||||
def lookup_revision_log_by_with_limit(o_id, br, ts, limit=per_page+1): | |||||
return service.lookup_revision_log_by(o_id, br, ts, limit) | |||||
error_msg = 'No revision matching origin %s ' % origin_id | |||||
error_msg += ', branch name %s' % branch_name | |||||
error_msg += (' and time stamp %s.' % ts) if ts else '.' | |||||
rev_get = api_lookup( | |||||
lookup_revision_log_by_with_limit, origin_id, branch_name, ts, | |||||
notfound_msg=error_msg, | |||||
enrich_fn=utils.enrich_revision) | |||||
nb_rev = len(rev_get) | |||||
if nb_rev == per_page+1: | |||||
revisions = rev_get[:-1] | |||||
last_sha1_git = rev_get[-1]['id'] | |||||
params = {k: v for k, v in {'origin_id': origin_id, | |||||
'branch_name': branch_name, | |||||
'ts': ts, | |||||
}.items() if v is not None} | |||||
query_params = {} | |||||
query_params['sha1_git'] = last_sha1_git | |||||
if request.query_params.get('per_page'): | |||||
query_params['per_page'] = per_page | |||||
result['headers'] = { | |||||
'link-next': reverse('api-revision-origin-log', url_args=params, | |||||
query_params=query_params) | |||||
} | |||||
else: | |||||
revisions = rev_get | |||||
result.update({'results': revisions}) | |||||
return result | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)/directory/', | |||||
'api-revision-origin-directory') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)/directory/(?P<path>.+)/', | |||||
'api-revision-origin-directory') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/directory/', | |||||
'api-revision-origin-directory') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/ts/(?P<ts>.+)/directory/', | |||||
'api-revision-origin-directory') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/directory/(?P<path>.+)/', | |||||
'api-revision-origin-directory') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/ts/(?P<ts>.+)' | |||||
r'/directory/(?P<path>.+)/', | |||||
'api-revision-origin-directory') | |||||
@api_doc('/revision/origin/directory/', tags=['hidden']) | |||||
def api_directory_through_revision_origin(request, origin_id, | |||||
branch_name="refs/heads/master", | |||||
ts=None, | |||||
path=None, | |||||
with_data=False): | |||||
""" | |||||
Display directory or content information through a revision identified | |||||
by origin/branch/timestamp. | |||||
""" | |||||
if ts: | |||||
ts = parse_timestamp(ts) | |||||
return _revision_directory_by({'origin_id': origin_id, | |||||
'branch_name': branch_name, | |||||
'ts': ts | |||||
}, | |||||
path, request.path, | |||||
with_data=with_data) | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)/', | |||||
'api-revision-origin') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/', | |||||
'api-revision-origin') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)' | |||||
r'/branch/(?P<branch_name>.+)/ts/(?P<ts>.+)/', | |||||
'api-revision-origin') | |||||
@api_route(r'/revision/origin/(?P<origin_id>[0-9]+)/ts/(?P<ts>.+)/', | |||||
'api-revision-origin') | |||||
@api_doc('/revision/origin/') | |||||
def api_revision_with_origin(request, origin_id, | |||||
branch_name="refs/heads/master", | |||||
ts=None): | |||||
""" | |||||
.. http:get:: /api/1/revision/origin/(origin_id)/[branch/(branch_name)/][ts/(timestamp)/] | |||||
Get information about a revision, searching for it based on software origin, | |||||
branch name, and/or visit timestamp. | |||||
This endpoint behaves like :http:get:`/api/1/revision/(sha1_git)/`, | |||||
but operates on the revision that has been found at a given software origin, | |||||
close to a given point in time, pointed by a given branch. | |||||
:param int origin_id: a software origin identifier | |||||
:param string branch_name: optional parameter specifying a fully-qualified branch name | |||||
associated to the software origin, e.g., "refs/heads/master". Defaults to the master branch. | |||||
:param string timestamp: optional parameter specifying a timestamp close to which the revision | |||||
pointed by the given branch should be looked up. The timestamp can be expressed either | |||||
as an ISO date or as a Unix one (in UTC). Defaults to now. | |||||
:reqheader Accept: the requested response content type, | |||||
either ``application/json`` (default) or ``application/yaml`` | |||||
:resheader Content-Type: this depends on :http:header:`Accept` header of request | |||||
:>json object author: information about the author of the revision | |||||
:>json string author_url: link to :http:get:`/api/1/person/(person_id)/` to get | |||||
information about the author of the revision | |||||
:>json object committer: information about the committer of the revision | |||||
:>json string committer_url: link to :http:get:`/api/1/person/(person_id)/` to get | |||||
information about the committer of the revision | |||||
:>json string committer_date: ISO representation of the commit date (in UTC) | |||||
:>json string date: ISO representation of the revision date (in UTC) | |||||
:>json string directory: the unique identifier that revision points to | |||||
:>json string directory_url: link to :http:get:`/api/1/directory/(sha1_git)/[(path)/]` | |||||
to get information about the directory associated to the revision | |||||
:>json string id: the revision unique identifier | |||||
:>json boolean merge: whether or not the revision corresponds to a merge commit | |||||
:>json string message: the message associated to the revision | |||||
:>json array parents: the parents of the revision, i.e. the previous revisions | |||||
that head directly to it, each entry of that array contains an unique parent | |||||
revision identifier but also a link to :http:get:`/api/1/revision/(sha1_git)/` | |||||
to get more information about it | |||||
:>json string type: the type of the revision | |||||
**Allowed HTTP Methods:** :http:method:`get`, :http:method:`head`, :http:method:`options` | |||||
:statuscode 200: no error | |||||
:statuscode 404: no revision matching the given criteria could be found in the archive | |||||
**Example:** | |||||
.. parsed-literal:: | |||||
:swh_web_api:`revision/origin/13706355/branch/refs/heads/2.7/` | |||||
""" # noqa | |||||
ts = parse_timestamp(ts) | |||||
return api_lookup( | |||||
service.lookup_revision_by, origin_id, branch_name, ts, | |||||
notfound_msg=('Revision with (origin_id: {}, branch_name: {}' | |||||
', ts: {}) not found.'.format(origin_id, | |||||
branch_name, ts)), | |||||
enrich_fn=utils.enrich_revision) | |||||
@api_route(r'/revision/(?P<sha1_git>[0-9a-f]+)/prev/(?P<context>[0-9a-f/]+)/', | @api_route(r'/revision/(?P<sha1_git>[0-9a-f]+)/prev/(?P<context>[0-9a-f/]+)/', | ||||
'api-revision-context') | 'api-revision-context') | ||||
@api_doc('/revision/prev/', tags=['hidden']) | @api_doc('/revision/prev/', tags=['hidden']) | ||||
def api_revision_with_context(request, sha1_git, context): | def api_revision_with_context(request, sha1_git, context): | ||||
""" | """ | ||||
Return information about revision with id sha1_git. | Return information about revision with id sha1_git. | ||||
""" | """ | ||||
def _enrich_revision(revision, context=context): | def _enrich_revision(revision, context=context): | ||||
▲ Show 20 Lines • Show All 222 Lines • Show Last 20 Lines |