def get(self, username, reponame): try: repo = (Repo.select().join(User).alias("user") .where((User.name == username) & (Repo.name == reponame)) .get()) title = repo.user.name + "/" + repo.name timemap = self.get_query_argument("timemap", "false") == "true" datetime = self.get_query_argument("datetime", None) key = self.get_query_argument("key", None) index = self.get_query_argument("index", "false") == "true" if self.get_query_argument("datetime", None): datestr = self.get_query_argument("datetime") try: ts = date(datestr, QSDATEFMT) except ValueError: raise HTTPError(reason="Invalid format of datetime param", status_code=400) elif "Accept-Datetime" in self.request.headers: datestr = self.request.headers.get("Accept-Datetime") ts = date(datestr, RFC1123DATEFMT) else: ts = now() if key and not timemap: chain = revision_logic.get_chain_at_ts(repo, key, ts) # use ts of cset instead of now(), to make prev work if len(chain) != 0: ts = chain[-1].time cs_prev = revision_logic.get_cset_prev_before_ts(repo, key, ts) cs_next = revision_logic.get_cset_next_after_ts(repo, key, ts) if cs_prev: cs_prev_str = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_prev.time.strftime(QSDATEFMT) else: cs_prev_str = "" if cs_next: cs_next_str = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_next.time.strftime(QSDATEFMT) else: cs_next_str = "" commit_message = revision_logic.get_commit_message(repo, key, ts) self.render("repo/memento.html", repo=repo, key=key, datetime=datetime, cs_next_str=cs_next_str, cs_prev_str=cs_prev_str, commit_message=commit_message) elif key and timemap: self.render("repo/history.html", repo=repo, key=key) elif index: cs = (CSet.select(fn.distinct(CSet.hkey)).where((CSet.repo == repo) & (CSet.time <= ts)).alias("cs")) key_count = (HMap.select(HMap.val).join(cs, on=(HMap.sha == cs.c.hkey_id))).count() page = int(self.get_query_argument("page", "1")) hm = revision_logic.get_repo_index(repo, ts, page) self.render("repo/index.html", repo=repo, title=title, key_count=key_count, page_size=revision_logic.INDEX_PAGE_SIZE, hm=hm, current_page=page) else: hm = list(revision_logic.get_repo_index(repo, ts, 1, 5)) # cs = (CSet.select(fn.distinct(CSet.hkey)).where(CSet.repo == repo).limit(5).alias("cs")) # samples = (HMap.select(HMap.val).join(cs, on=(HMap.sha == cs.c.hkey_id))) self.render("repo/show.html", title=title, repo=repo, hm=hm) except Repo.DoesNotExist: raise HTTPError(reason="Repo not found.", status_code=404)
def __get_next_memento(self, repo, key, ts): return revision_logic.get_cset_next_after_ts(repo, key, ts)
def __get_revision(self, repo, key, ts, header_only=False): # Recreate the resource for the given key # - in its latest state (if no `datetime` was provided) or # - in the state it was in at the time indicated by the passed `datetime` argument. if not header_only: self.set_header("Content-Type", "application/n-quads") self.set_header("Vary", "accept-datetime") chain = revision_logic.get_chain_at_ts(repo, key, ts) if len(chain) == 0: raise HTTPError(reason="Resource not found in repo.", status_code=404) # if no datetime given, ts will be now(), therefor cs_prev and cs_next won't work # therefore get time of last cset in chain ts = chain[-1].time timegate_url = (self.request.protocol + "://" + self.request.host + self.request.path) + "?key=" + key timemap_url = (self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&timemap=true") link_header = ( '<%s>; rel="original"' ', <%s>; rel="timegate"' ', <%s>; rel="timemap"' % (key, timegate_url, timemap_url)) cs_first = revision_logic.get_first_cset_of_repo(repo, key) cs_last = revision_logic.get_last_cset_of_repo(repo, key) cs_prev = revision_logic.get_cset_prev_before_ts(repo, key, ts) cs_next = revision_logic.get_cset_next_after_ts(repo, key, ts) cs_first_url = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_first.time.strftime(QSDATEFMT) if cs_first.time == cs_last.time: # only one CSet link_header += (', <%s>; rel="first last memento"; datetime="%s"' % (cs_first_url, cs_first.time.strftime(RFC1123DATEFMT))) else: # more than one CSet --> first != last cs_last_url = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_last.time.strftime(QSDATEFMT) if cs_prev: cs_prev_url = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_prev.time.strftime(QSDATEFMT) if cs_prev.time == cs_first.time: link_header += (', <%s>; rel="prev first memento"; datetime="%s"' % (cs_prev_url, cs_prev.time.strftime(RFC1123DATEFMT))) else: link_header += (', <%s>; rel="first memento"; datetime="%s"' % (cs_first_url, cs_first.time.strftime(RFC1123DATEFMT))) link_header += (', <%s>; rel="prev memento"; datetime="%s"' % (cs_prev_url, cs_prev.time.strftime(RFC1123DATEFMT))) else: link_header += (', <%s>; rel="first memento"; datetime="%s"' % (cs_first_url, cs_first.time.strftime(RFC1123DATEFMT))) if cs_next: cs_next_url = self.request.protocol + "://" + self.request.host + self.request.path + "?key=" + key + "&datetime=" + cs_next.time.strftime(QSDATEFMT) if cs_next.time == cs_last.time: link_header += (', <%s>; rel="next last memento"; datetime="%s"' % (cs_next_url, cs_next.time.strftime(RFC1123DATEFMT))) else: link_header += (', <%s>; rel="next memento"; datetime="%s"' % (cs_next_url, cs_next.time.strftime(RFC1123DATEFMT))) link_header += (', <%s>; rel="last memento"; datetime="%s"' % (cs_last_url, cs_last.time.strftime(RFC1123DATEFMT))) else: link_header += (', <%s>; rel="last memento"; datetime="%s"' % (cs_last_url, cs_last.time.strftime(RFC1123DATEFMT))) self.set_header("Memento-Datetime", chain[-1].time.strftime(RFC1123DATEFMT)) self.set_header("Link", link_header) if not header_only: if chain[0].type == CSet.DELETE: # The last change was a delete. Return a 404 response with # appropriate "Link" and "Memento-Datetime" headers. raise HTTPError(reason="Resource does not exist at that time (has been deleted).", status_code=404) stmts = revision_logic.get_revision(repo, key, chain) self.write(join(stmts, "\n"))