commit - ba63ab46fb6570dd4cfacb1643a3a8fe5c68b835
commit + 85c360aaa1efe49063956a1fdfd7e46d8e5a92b3
blob - 6e6a2e8391b5ff02c1bdb7753f0ec1b51a1ff8a9
blob + cb4f8f8e680b39482cbb9ddec60bee5c76db72a6
--- README
+++ README
See regress/gotd/README for information about running the server test suite.
-Game of Trees Web (Gotweb) is a CGI program which displays repository data
-and is designed to work with httpd(8) and slowcgi(8). It requires the Kristaps
-Dzonsons kcgi library, version 0.12.0 or greater.
+Game of Trees Daemon (gotwebd) is a FastCGI program which displays repository
+data and is designed to work with httpd(8).
-To compile gotweb on OpenBSD, run:
+To compile gotwebd on OpenBSD, run:
- # pkg_add kcgi
- $ make web
- # make web-install
+ $ make webd
+ # make webd-install
This will create the following files:
- the CGI program /var/www/cgi-bin/gotweb/gotweb
- helper programs from the libexec directory in /var/www/cgi-bin/gotweb/libexec
- several template files in /var/www/cgi-bin/gw_tmpl/
- html, css, and image files in /var/www/htdocs/gotweb/
- the directory /var/www/got/tmp/
+ the daemon program /usr/local/sbin/gotwebd
+ css and image files in /var/www/htdocs/gotwebd
+ the gotwebd init script in /etc/rc.d
man pages (only installed if building sources from a Got release tarball)
Documentation is available in manual pages:
- $ man -l gotweb/gotweb.8
- $ man -l gotweb/gotweb.conf.5
+ $ man -l gotwebd/gotwebd.8
+ $ man -l gotwebd/gotwebd.conf.5
Got can be built with profiling enabled to debug performance issues.
$ doas pkg_add gprof2dot graphviz
$ gprof ~/bin/got-read-pack gmon.out | gprof2dot | dot -T png > profile.png
-As another example, to compile gotweb with profiling enabled:
- $ cd gotweb
- $ make clean
- $ make PROFILE=1 gotweb
- $ make # compile remaining gotweb binaries as usual
- $ doas make install
- $ doas chown www /var/www/cgi-bin/gotweb/
-
-After loading a gotweb page in the browser, there should now
-be a gmon.out file next to the gotweb binary:
-
-$ ls -l /var/www/cgi-bin/gotweb/
-total 6088
--rw-r--r-- 1 www daemon 427642 Jun 17 22:04 gmon.out
--rwxr-xr-x 1 www www 2630488 Jun 17 22:03 gotweb
-drwxr-xr-x 2 root daemon 512 Jun 17 22:03 gw_tmpl
-drwxr-xr-x 2 root daemon 512 Jun 17 22:03 libexec
-
-
Guidelines for reporting problems:
All problem/bug reports should include a reproduction recipe in form of a
blob - ae4b3d19d689e504703a7a34bf04a9ba4607fde8
blob + e754777a9202afca9a7b80dfd634b3c605d8a5cd
--- got/got.1
+++ got/got.1
.Xr git-repository 5 ,
.Xr got-worktree 5 ,
.Xr got.conf 5 ,
-.Xr gotweb 8
+.Xr gotwebd 8
.Sh AUTHORS
.An Anthony J. Bentley Aq Mt bentley@openbsd.org
.An Christian Weisgerber Aq Mt naddy@openbsd.org
.Nm ,
.Xr tog 1 ,
and
-.Xr gotweb 8
+.Xr gotwebd 8
were derived from code under copyright by:
.Pp
.An Caldera International
blob - e85f3f4271c437daae68be411b08e6808d317293
blob + 1ead58d255acf59cc3547c69f091a88b2a8e2102
--- got-dist.txt
+++ got-dist.txt
/gotsh/Makefile
/gotsh/gotsh.1
/gotsh/gotsh.c
-/gotweb
-/gotweb/Makefile
-/gotweb/Makefile.inc
-/gotweb/files
-/gotweb/files/cgi-bin
-/gotweb/files/cgi-bin/gw_tmpl
-/gotweb/files/cgi-bin/gw_tmpl/blame.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/briefs.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/commit.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/diff.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/err.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/index.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/summry.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/tag.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/tags.tmpl
-/gotweb/files/cgi-bin/gw_tmpl/tree.tmpl
-/gotweb/files/htdocs
-/gotweb/files/htdocs/gotweb
-/gotweb/files/htdocs/gotweb/android-chrome-192x192.png
-/gotweb/files/htdocs/gotweb/android-chrome-384x384.png
-/gotweb/files/htdocs/gotweb/apple-touch-icon.png
-/gotweb/files/htdocs/gotweb/browserconfig.xml
-/gotweb/files/htdocs/gotweb/favicon-16x16.png
-/gotweb/files/htdocs/gotweb/favicon-32x32.png
-/gotweb/files/htdocs/gotweb/favicon.ico
-/gotweb/files/htdocs/gotweb/got.png
-/gotweb/files/htdocs/gotweb/got_large.png
-/gotweb/files/htdocs/gotweb/gotweb.css
-/gotweb/files/htdocs/gotweb/index.html
-/gotweb/files/htdocs/gotweb/mstile-150x150.png
-/gotweb/files/htdocs/gotweb/safari-pinned-tab.svg
-/gotweb/files/htdocs/gotweb/site.webmanifest
-/gotweb/gotweb.8
-/gotweb/gotweb.c
-/gotweb/gotweb.conf.5
-/gotweb/gotweb.h
-/gotweb/libexec
-/gotweb/libexec/Makefile
-/gotweb/libexec/Makefile.inc
-/gotweb/libexec/got-read-blob
-/gotweb/libexec/got-read-blob/Makefile
-/gotweb/libexec/got-read-commit
-/gotweb/libexec/got-read-commit/Makefile
-/gotweb/libexec/got-read-gitconfig
-/gotweb/libexec/got-read-gitconfig/Makefile
-/gotweb/libexec/got-read-gotconfig
-/gotweb/libexec/got-read-gotconfig/Makefile
-/gotweb/libexec/got-read-object
-/gotweb/libexec/got-read-object/Makefile
-/gotweb/libexec/got-read-pack
-/gotweb/libexec/got-read-pack/Makefile
-/gotweb/libexec/got-read-tag
-/gotweb/libexec/got-read-tag/Makefile
-/gotweb/libexec/got-read-tree
-/gotweb/libexec/got-read-tree/Makefile
-/gotweb/parse.y
/gotwebd
/gotwebd/Makefile
/gotwebd/Makefile.inc
blob - 3f9b3180520b398deed0f58abea911812958de70 (mode 644)
blob + /dev/null
--- gotweb/Makefile
+++ /dev/null
-.PATH:${.CURDIR}/../lib
-
-SUBDIR = libexec
-
-.include "../got-version.mk"
-.include "Makefile.inc"
-
-PROG = gotweb
-SRCS = gotweb.c parse.y blame.c commit_graph.c delta.c diff.c \
- diffreg.c error.c object.c object_cache.c \
- object_idset.c object_parse.c opentemp.c path.c pack.c \
- privsep.c reference.c repository.c sha1.c \
- inflate.c buf.c rcsutil.c diff3.c lockfile.c \
- deflate.c object_create.c delta_cache.c gotconfig.c \
- diff_main.c diff_atomize_text.c diff_myers.c diff_output.c \
- diff_output_plain.c diff_output_unidiff.c \
- diff_output_edscript.c diff_patience.c \
- bloom.c murmurhash2.c sigs.c date.c object_open_privsep.c \
- read_gitconfig_privsep.c read_gotconfig_privsep.c \
- pollfd.c reference_parse.c
-MAN = ${PROG}.conf.5 ${PROG}.8
-
-CPPFLAGS += -I${.CURDIR}/../include -I${.CURDIR}/../lib -I${.CURDIR} \
- -I${KCGIBASE}/include
-LDADD += -L${KCGIBASE}/lib -lkcgihtml -lkcgi -lz -lm
-LDSTATIC = ${STATIC}
-
-.if ${GOT_RELEASE} != "Yes"
-NOMAN = Yes
-.endif
-
-realinstall:
- if [ ! -d ${DESTDIR}${CGI_DIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 ${DESTDIR}${CGI_DIR}; \
- fi
- if [ ! -d ${DESTDIR}${PUB_REPOS_DIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 ${DESTDIR}${PUB_REPOS_DIR}; \
- fi
- ${INSTALL} -c -o ${WWWUSR} -g ${WWWGRP} -m 0755 ${PROG} \
- ${DESTDIR}${CGI_DIR}/${PROG}
- if [ ! -d ${DESTDIR}${TMPL_DIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 ${DESTDIR}${TMPL_DIR}; \
- fi
- ${INSTALL} -c -o ${WWWUSR} -g ${WWWGRP} -m 0755 \
- ${.CURDIR}/files/cgi-bin/gw_tmpl/* ${DESTDIR}${TMPL_DIR}
- if [ ! -d ${DESTDIR}${HTTPD_DIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 ${DESTDIR}${HTTPD_DIR}; \
- fi
- if [ ! -d ${DESTDIR}${TMP_DIR}/. ]; then \
- ${INSTALL} -d -o ${WWWUSR} -g ${WWWGRP} -m 755 ${DESTDIR}${TMP_DIR}; \
- fi
- if [ ! -d ${DESTDIR}${PROG_DIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 ${DESTDIR}${PROG_DIR}; \
- fi
- ${INSTALL} -c -o ${WWWUSR} -g ${WWWGRP} -m 0755 \
- ${.CURDIR}/files/htdocs/${PROG}/* ${DESTDIR}${PROG_DIR}
-
-.include <bsd.prog.mk>
blob - f6a499dbd885b285605963a25b23076855a8786f (mode 644)
blob + /dev/null
--- gotweb/Makefile.inc
+++ /dev/null
-KCGIBASE ?= /usr/local
-LDADD += -lz -lutil
-LDSTATIC = ${STATIC}
-CHROOT_DIR ?= /var/www
-GOTWEB_DIR = /cgi-bin/gotweb
-LIBEXECDIR = ${GOTWEB_DIR}/libexec
-LIBEXEC_DIR = ${CHROOT_DIR}${LIBEXECDIR}
-ETC_DIR = ${CHROOT_DIR}/etc
-HTTPD_DIR = ${CHROOT_DIR}/htdocs
-GOTWEB_TMP_DIR ?= /got/tmp
-TMP_DIR = ${CHROOT_DIR}${GOTWEB_TMP_DIR}
-PROG_DIR = ${HTTPD_DIR}/${PROG}
-CGI_DIR = ${CHROOT_DIR}${GOTWEB_DIR}
-TMPL_DIR = ${CGI_DIR}/gw_tmpl
-PUB_REPOS_DIR = ${CHROOT_DIR}/got/public
-WWWUSR ?= www
-WWWGRP ?= www
-
-CPPFLAGS += -DGOT_TMPDIR=${GOTWEB_TMP_DIR}
-
-.if defined(PROFILE)
-CPPFLAGS += -DPROFILE
-DEBUG = -O0 -pg -g -static
-.else
-DEBUG = -O0 -g
-.endif
blob - 64237d2f0dec8688ccd27965e4b944d1a3ca6d8e (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/blame.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='blame_title_wrapper'>
- <div id='blame_title'>Blame</div>
- </div>
- <div id='blame_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 53d8e825b7ea9995ba68ecbc6a02e8a75f0ced59 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/briefs.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='briefs_title_wrapper'>
- <div id='briefs_title'>Commit Briefs</div>
- </div>
- <div id='briefs_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - ef504f03cfeb9e20af5a92e2c4d3801ee5cb9650 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/commit.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='commits_title_wrapper'>
- <div id='commits_title'>Commits</div>
- </div>
- <div id='commits_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 6a466f25e20dd30349a4913eab6019f62fbfe04a (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/diff.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='diff_title_wrapper'>
- <div id='diff_title'>Commit Diff</div>
- </div>
- <div id='diff_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 52b2cb624d22803080950f1af69d72ea818f9fd8 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/err.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='err_title_wrapper'>
- <div id='err_title'>Error</div>
- </div>
- <div id='err_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 12819268eddbfa9b3a5d68d8897c937bb20f7cd4 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/index.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- @@content@@
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 12819268eddbfa9b3a5d68d8897c937bb20f7cd4 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/summry.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- @@content@@
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 1867b81cba52c7f0a18b2b931b0d91b92ad52a85 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/tag.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='tag_title_wrapper'>
- <div id='tag_title'>Tag</div>
- </div>
- <div id='tag_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - 12819268eddbfa9b3a5d68d8897c937bb20f7cd4 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/tags.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- @@content@@
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - f7c5a935c98101e547c6c513143bf0096ae1c610 (mode 644)
blob + /dev/null
--- gotweb/files/cgi-bin/gw_tmpl/tree.tmpl
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <title>@@title@@</title>
- @@head@@
- </head>
- <body>
- <div id="gw_body">
- <div id="header">
- @@header@@
- </div>
- <div id="site_path">
- @@sitepath@@
- @@search@@
- </div>
- <div id="content">
- <div id='tree_title_wrapper'>
- <div id='tree_title'>Tree</div>
- </div>
- <div id='tree_content'>
- @@content@@
- </div>
- </div>
- @@siteowner@@
- </div>
- </body>
-</html>
blob - f841f054bc2941b0cdca7e496ea69621671d6766 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/android-chrome-192x192.png and /dev/null differ
blob - 653a1510ce933f7fe9fbab2fcd171f04fa0b24cc (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/android-chrome-384x384.png and /dev/null differ
blob - 460aa1299f8e9f37773618bcab2619794416fb49 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/apple-touch-icon.png and /dev/null differ
blob - b3930d0f047184047cb81d620436d91653438b8b (mode 644)
blob + /dev/null
--- gotweb/files/htdocs/gotweb/browserconfig.xml
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<browserconfig>
- <msapplication>
- <tile>
- <square150x150logo src="/mstile-150x150.png"/>
- <TileColor>#da532c</TileColor>
- </tile>
- </msapplication>
-</browserconfig>
blob - f6c1a7c289faa4a48e03c97e68b1ba7a11dfddd1 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/favicon-16x16.png and /dev/null differ
blob - 0ceea8c0eabe73e8d12cf106d73c34abb1999cb2 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/favicon-32x32.png and /dev/null differ
blob - ee414573031ea5b310539196d2530a1e52d49b64 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/favicon.ico and /dev/null differ
blob - 33933f80ee46217039804bc96672ede12b352b93 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/got.png and /dev/null differ
blob - 97ace786464b193baf1cd51e54016aea3016e62f (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/got_large.png and /dev/null differ
blob - eb7e67f6b7ca0ddd442d0f8f38810ba7846efae1 (mode 644)
blob + /dev/null
--- gotweb/files/htdocs/gotweb/gotweb.css
+++ /dev/null
-/*
- * Copyright (c) 2019 Jerome Kasper <neon.king.fr@gmail.com>
- * Copyright (c) 2019, 2020 Tracey Emery <tracey@traceyemery.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* general sections */
-
-a {
- color: #444444;
- text-decoration: none;
-}
-a:hover {
- color: Gold;
- text-decoration: none;
-}
-body {
- background-color: #ffffff;
- color: #000000;
- margin: 0;
- padding: 0;
- font-family: Arial, sans-serif;
-}
-
-.diff_minus, .diff_submodule {
- color: magenta;
-}
-.diff_plus, .diff_symlink, .diff_author {
- color: darkcyan;
-}
-.diff_chunk_header, .diff_date {
- background-color: LightSlateGray;
- color: yellow;
-}
-.diff_meta, .diff_executable, .diff_commit {
- color: green;
-}
-.diff_directory {
- color: blue;
-}
-
-.back_white {
- background-color: #ffffff;
-}
-.back_lightgray {
- background-color: #d8f3ef;
-}
-
-#refs_str {
- background-color: #243647;
- color: #ffffff;
- font-style: italic;
-}
-#dotted_line {
- clear: left;
- float: left;
- width: 100%;
- border-top: 1px dotted #444444;
-}
-#solid_line {
- clear: left;
- float: left;
- width: 100%;
- border-top: 1px solid #444444;
-}
-#header {
- overflow: auto;
- width: 100%;
- background-image: linear-gradient(to right, White, LightSlateGray);
-}
-#header a {
- color: #ffffff;
- font-size: 1.2em;
- text-decoration: none;
-}
-#header a:hover {
- color: Gold;
- font-size: 1.2em;
- text-decoration: none;
-}
-#site_path {
- clear: left;
- float: left;
- overflow: auto;
- width: 100%;
- background-color: #243647;
-}
-#site_link {
- float: left;
- width: 40%;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- color: #ffffff;
- overflow: hidden;
-}
-#site_link a {
- color: #ffffff;
- text-decoration: none;
-}
-#search {
- float: right;
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#got_link {
- float: left;
- padding-bottom: 10px;
- padding-top: 10px;
-}
-#content {
- width: 100%;
-}
-#np_wrapper {
- clear: left;
- float: left;
- width: 100%;
- border-bottom: 1px dotted #444444;
- background-color: #f5fcfb;
- overflow: hidden;
-}
-#nav_prev {
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- overflow: visible;
-}
-#nav_next {
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- text-align: right;
- overflow: hidden;
-}
-#navs_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: #ced7e0;
-}
-#navs {
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
- font-size: .8em;
-}
-#site_owner_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#site_owner {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#description_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#description {
- float: left;
- width: 72%;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#repo_owner_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#repo_owner {
- float: left;
- width: 72%;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#last_change_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#last_change {
- float: left;
- width: 72%;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#cloneurl_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#cloneurl {
- float: left;
- width: 72%;
- padding-top: 5px;
- padding-bottom: 5px;
- overflow: auto;
- white-space: pre-wrap;
-}
-#tmpl_err {
- clear: left;
- float: left;
- padding-left: 20px;
- padding-top: 20px;
- padding-bottom: 20px;
- white-space: pre-wrap;
-}
-
-/* headers */
-
-#header_commit_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_commit {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_diff_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_diff {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_author_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_author {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_committer_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_committer {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_age_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_age {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_commit_msg_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_commit_msg {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
- white-space: pre-wrap;
-}
-#header_tree_title {
- clear: left;
- float: left;
- width: 6.5em;
- padding-left: 10px;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-#header_tree {
- float: left;
- width: 72%;
- padding-top: 2px;
- padding-bottom: 2px;
-}
-
-/* heads.tmpl */
-
-#heads_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#heads_age {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- float: left;
- width: 7.5em;
- overflow: auto;
-}
-#heads_space {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- float: left;
- width: 8.5em;
- overflow: auto;
-}
-#head {
- float: left;
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-
-/* err.tmpl */
-
-#err_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#err_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#err_content {
- clear: left;
- float: left;
- width: 100%;
- padding-left: 20px;
- padding-top: 20px;
- padding-bottom: 20px;
-}
-
-/* briefs.tmpl */
-
-#briefs_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#briefs_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#briefs_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#briefs_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#briefs_age {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- float: left;
- width: 7.5em;
- overflow: auto;
-}
-#briefs_author {
- float: left;
- padding-top: 5px;
- padding-bottom: 5px;
- width: 8.5em;
- font-style: italic;
- overflow: auto;
-}
-#briefs_log {
- float: left;
- padding-left: 10px;
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- width: 65%;
-}
-/* index.tmpl */
-
-#index_header {
- clear: left;
- float: left;
- overflow: auto;
- width: 100%;
- background-color: Khaki;
-}
-#index_header_project {
- clear: left;
- float: left;
- width: 20%;
- padding: 10px;
-}
-#index_header_description {
- float: left;
- width: 30%;
- padding: 10px;
-}
-#index_header_owner {
- float: left;
- width: 12%;
- padding: 10px;
-}
-#index_header_age {
- padding: 10px;
- overflow: hidden;
-}
-#index_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#index_project {
- float: left;
- width: 20%;
- padding: 10px;
- overflow: hidden;
-}
-#index_project_description {
- float: left;
- width: 30%;
- padding: 10px;
- overflow: auto;
-}
-#index_project_owner {
- float: left;
- width: 12%;
- padding: 10px;
- overflow: hidden;
-}
-#index_project_age {
- float: left;
- width: 14%;
- padding: 10px;
- overflow: visible;
-}
-#index_project a {
- color: #444444;
- text-decoration: none;
-}
-#index_project a:hover {
- color: SteelBlue;
- text-decoration: none;
-}
-#index_project_navs a {
- color: #444444;
- text-decoration: none;
-}
-#index_project_navs a:hover {
- color: SteelBlue;
- text-decoration: none;
-}
-#index_next a {
- color: #444444;
- text-decoration: none;
-}
-#index_next a:hover {
- color: SteelBlue;
- text-decoration: none;
-}
-#index_prev a {
- color: #444444;
- text-decoration: none;
-}
-#index_prev a:hover {
- color: SteelBlue;
- text-decoration: none;
-}
-
-/* commit.tmpl */
-
-#commits_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#commits_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#commits_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#commits_line_wrapper {
- clear: left;
- float: left;
- background-color: #f5fcfb;
- padding-top: 3px;
- padding-bottom: 3px;
- width: 100%;
-}
-#commit {
- clear: left;
- float: left;
- padding-left: 20px;
- padding-top: 20px;
- padding-bottom: 20px;
- white-space: pre-wrap;
-}
-
-/* blame.tmpl */
-
-#blame_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#blame_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#blame_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#blame_header_wrapper {
- float: left;
- background-color: #f5fcfb;
- width: 100%;
-}
-#blame_header {
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 2px;
- width: 80%;
-}
-#blame {
- clear: left;
- float: left;
- margin-left: 20px;
- margin-top: 20px;
- margin-bottom: 20px;
- font-family: monospace;
- white-space: pre;
- overflow: auto;
-}
-#blame_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#blame_number {
- float: left;
- width: 3em;
- overflow: hidden;
-}
-#blame_hash {
- float: left;
- width: 6em;
- overflow: auto;
-}
-#blame_date {
- float: left;
- width: 7em;
- overflow: auto;
-}
-#blame_author {
- float: left;
- width: 6em;
- overflow: hidden;
-}
-#blame_code {
- float:left;
- width: 50%;
- overflow: visible;
-}
-
-/* tree.tmpl */
-
-#tree_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#tree_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#tree_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#tree_header_wrapper {
- clear: left;
- float: left;
- background-color: #f5fcfb;
- width: 100%;
-}
-#tree_header {
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 2px;
- width: 80%;
-}
-#tree {
- clear: left;
- float: left;
- margin-left: 20px;
- margin-top: 20px;
- margin-bottom: 20px;
- font-family: monospace;
-}
-#tree_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#tree_line {
- clear: left;
- float: left;
- width: 20em;
- padding: 1px;
-}
-#tree_line_blank {
- float: left;
- padding: 1px;
- width: 8em;
-}
-#tree_line_navs {
- float: left;
- text-align: right;
- padding: 1px;
- width: 8em;
-}
-
-/* tag.tmpl */
-
-#tag_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#tag_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#tag_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#tag_header_wrapper {
- clear: left;
- float: left;
- background-color: #f5fcfb;
- width: 100%;
-}
-#tag_header {
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 2px;
- width: 80%;
-}
-#tag_wrapper {
- clear: left;
- float: left;
- width: 100%;
-}
-#tag_age {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- float: left;
- width: 7.5em;
- overflow: auto;
-}
-#tag {
- float: left;
- width: 8.5em;
- font-style: italic;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#tag_name {
- float: left;
- padding-left: 10px;
- padding-right: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#tag_info_date_title {
- clear: left;
- float: left;
- width: 7.5em;
-}
-#tag_info_date {
- float: left;
-}
-#tag_info_tagger_title {
- clear: left;
- float: left;
- width: 7.5em;
-}
-#tag_info_tagger {
- float: left;
-}
-#tag_info {
- clear: left;
- float: left;
- margin-top: 25px;
- white-space: pre-wrap;
-}
-
-/* tags.tmpl */
-#tags_info {
- clear: left;
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-
-
-/* diff.tmpl */
-
-#diff_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#diff_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#diff_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#diff_header_wrapper {
- float: left;
- background-color: #f5fcfb;
- width: 100%;
-}
-#diff_header {
- float: left;
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 2px;
- width: 80%;
-}
-#diff {
- clear: left;
- float: left;
- margin-left: 20px;
- margin-top: 20px;
- margin-bottom: 20px;
- font-family: monospace;
- white-space: pre;
-}
-
-/* summary.tmpl */
-
-#summary_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: Khaki;
-}
-#summary_tags_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#summary_tags_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#summary_tags_content {
- clear: left;
- float: left;
- width: 100%;
-}
-#summary_heads_title_wrapper {
- clear: left;
- float: left;
- width: 100%;
- background-color: LightSlateGray;
- color: #ffffff;
-}
-#summary_heads_title {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
-}
-#summary_heads_content {
- clear: left;
- float: left;
- width: 100%;
-}
blob - 791e49544c8c5f82a710137fee5a2a4becaad616 (mode 644)
blob + /dev/null
--- gotweb/files/htdocs/gotweb/index.html
+++ /dev/null
-<!DOCTYPE html>
-<html>
- <head>
- <meta http-equiv="Refresh" content="0; url=/cgi-bin/gotweb/gotweb" />
- </head>
- <body>
- <p><a href="/cgi-bin/gotweb/gotweb">gotweb</a></p>
- </body>
-</html>
\ No newline at end of file
blob - 0c47027971e9e0a5060e23fe73e7cb0399eacea8 (mode 644)
blob + /dev/null
Binary files gotweb/files/htdocs/gotweb/mstile-150x150.png and /dev/null differ
blob - 96e67c7c4b7cb9b1b395281fae8d7cffa834a991 (mode 644)
blob + /dev/null
--- gotweb/files/htdocs/gotweb/safari-pinned-tab.svg
+++ /dev/null
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
- "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
-<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
- width="400.000000pt" height="400.000000pt" viewBox="0 0 400.000000 400.000000"
- preserveAspectRatio="xMidYMid meet">
-<metadata>
-Created by potrace 1.11, written by Peter Selinger 2001-2013
-</metadata>
-<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)"
-fill="#000000" stroke="none">
-<path d="M0 1995 l0 -1215 2000 0 2000 0 0 1215 0 1215 -2000 0 -2000 0 0
--1215z"/>
-</g>
-</svg>
blob - a1553eb86b573da072c732c9aabac5a80968461f (mode 644)
blob + /dev/null
--- gotweb/files/htdocs/gotweb/site.webmanifest
+++ /dev/null
-{
- "name": "",
- "short_name": "",
- "icons": [
- {
- "src": "/android-chrome-192x192.png",
- "sizes": "192x192",
- "type": "image/png"
- },
- {
- "src": "/android-chrome-384x384.png",
- "sizes": "384x384",
- "type": "image/png"
- }
- ],
- "theme_color": "#ffffff",
- "background_color": "#ffffff",
- "display": "standalone"
-}
blob - df516d6285a1ca6f473e533e05556b5395d506fe (mode 644)
blob + /dev/null
--- gotweb/gotweb.8
+++ /dev/null
-.\"
-.\" Copyright (c) 2020 Stefan Sperling
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate$
-.Dt GOTWEB 8
-.Os
-.Sh NAME
-.Nm gotweb
-.Nd Game of Trees Git repository server for web browsers
-.Sh SYNOPSIS
-.Nm
-.Sh DESCRIPTION
-.Nm
-provides a web interface allowing Git repository contents to be viewed
-with a web browser.
-.Pp
-.Nm
-is a CGI program based on
-.Xr got 1
-and
-.Xr kcgi 3
-which is intended to run in a
-.Xr chroot 2
-environment in
-.Pa /var/www .
-The program has been designed to work out of the box with
-the
-.Xr httpd 8
-web server in conjunction with
-.Xr slowcgi 8 .
-.Pp
-Enabling
-.Nm
-requires the following steps:
-.Bl -enum
-.It
-The
-.Xr httpd.conf 5
-configuration file must be adjusted to run
-.Nm
-as a CGI program with
-.Xr slowcgi 8 .
-The
-.Sx EXAMPLES
-section below contains an appropriate configuration file sample.
-.It
-httpd(8) and slowcgi(8) must be enabled and started:
-.Bd -literal -offset indent
- # rcctl enable httpd slowcgi
- # rcctl start httpd slowcgi
-.Ed
-.It
-Optionally, the run-time behaviour of
-.Nm
-can be configured via the
-.Xr gotweb.conf 5
-configuration file.
-.It
-Git repositories must be created at a suitable location inside the
-web server's
-.Xr chroot 2
-environment.
-These repositories should
-.Em not
-be writable by the user ID of the
-.Xr httpd 8
-server.
-The default location for repositories published by
-.Nm
-is
-.Pa /var/www/got/public .
-.It
-Git repositories served by
-.Nm
-should be kept up-to-date with a mechanism such as
-.Cm got fetch ,
-.Xr git-fetch 1 ,
-or
-.Xr rsync 1 ,
-scheduled by
-.Xr cron 8 .
-.El
-.Sh FILES
-.Bl -tag -width /var/www/got/public/ -compact
-.It Pa /var/www/got/public/
-Default location for Git repositories served by
-.Nm .
-This location can be adjusted in the
-.Xr gotweb.conf 5
-configuration file.
-.It Pa /var/www/cgi-bin/gotweb/gotweb
-The
-.Nm
-CGI program, statically linked for use in a
-.Xr chroot 2
-environment.
-.It Pa /var/www/cgi-bin/gotweb/gw_tmpl/
-Directory for template files used by
-.Nm .
-.It Pa /var/www/cgi-bin/gotweb/libexec/
-Directory containing statically linked
-.Xr got 1
-helper programs which are run by
-.Nm
-to read Git repositories.
-.It Pa /var/www/htdocs/gotweb/
-Directory containing HTML, CSS, and image files used by
-.Nm .
-.It Pa /var/www/got/tmp/
-Directory for temporary files created by
-.Nm .
-.El
-.Sh EXAMPLES
-Example configuration for httpd.conf:
-.Bd -literal -offset indent
-
- types { include "/usr/share/misc/mime.types" }
- server "gotweb.example.com" {
- listen on * port 80
- root "/htdocs/gotweb"
- location "/cgi-bin/*" {
- root "/"
- fastcgi
- }
- location "/*" {
- directory index "index.html"
- }
- }
-.Ed
-.Sh SEE ALSO
-.Xr got 1 ,
-.Xr kcgi 3 ,
-.Xr git-repository 5 ,
-.Xr gotweb.conf 5 ,
-.Xr httpd 8 ,
-.Xr slowcgi 8
-.Sh AUTHORS
-.An Christian Weisgerber Aq Mt naddy@openbsd.org
-.An Jerome Kasper Aq Mt neon.king.fr@gmail.com
-.An Josh Rickmar Aq Mt jrick@zettaport.com
-.An Omar Polo Aq Mt op@openbsd.org
-.An Stefan Sperling Aq Mt stsp@openbsd.org
-.An Tracey Emery Aq Mt tracey@traceyemery.net
blob - 0580992091e15b774b51ac00db28f4d691a4b1a0 (mode 644)
blob + /dev/null
--- gotweb/gotweb.c
+++ /dev/null
-/*
- * Copyright (c) 2019, 2020 Tracey Emery <tracey@traceyemery.net>
- * Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <dirent.h>
-#include <err.h>
-#include <errno.h>
-#include <regex.h>
-#include <sha1.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <got_error.h>
-#include <got_object.h>
-#include <got_reference.h>
-#include <got_repository.h>
-#include <got_path.h>
-#include <got_cancel.h>
-#include <got_worktree.h>
-#include <got_diff.h>
-#include <got_commit_graph.h>
-#include <got_blame.h>
-#include <got_privsep.h>
-#include <got_opentemp.h>
-
-#include <kcgi.h>
-#include <kcgihtml.h>
-
-#include "gotweb.h"
-
-#ifndef nitems
-#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
-#endif
-
-struct gw_trans {
- TAILQ_HEAD(headers, gw_header) gw_headers;
- TAILQ_HEAD(dirs, gw_dir) gw_dirs;
- struct got_repository *repo;
- struct gw_dir *gw_dir;
- struct gotweb_config *gw_conf;
- struct ktemplate *gw_tmpl;
- struct khtmlreq *gw_html_req;
- struct kreq *gw_req;
- const struct got_error *error;
- const char *repo_name;
- char *repo_path;
- char *commit_id;
- char *next_id;
- char *prev_id;
- const char *repo_file;
- char *repo_folder;
- const char *headref;
- unsigned int action;
- unsigned int page;
- unsigned int repos_total;
- enum kmime mime;
- int *pack_fds;
-};
-
-struct gw_header {
- TAILQ_ENTRY(gw_header) entry;
- struct got_reflist_head refs;
- char *path;
-
- char *refs_str;
- char *commit_id; /* id_str1 */
- char *parent_id; /* id_str2 */
- char *tree_id;
- char *author;
- char *committer;
- char *commit_msg;
- time_t committer_time;
-};
-
-struct gw_dir {
- TAILQ_ENTRY(gw_dir) entry;
- char *name;
- char *owner;
- char *description;
- char *url;
- char *age;
- char *path;
-};
-
-enum gw_key {
- KEY_ACTION,
- KEY_COMMIT_ID,
- KEY_FILE,
- KEY_FOLDER,
- KEY_HEADREF,
- KEY_PAGE,
- KEY_PATH,
- KEY_PREV_ID,
- KEY__ZMAX
-};
-
-enum gw_tmpl {
- TEMPL_CONTENT,
- TEMPL_HEAD,
- TEMPL_HEADER,
- TEMPL_SEARCH,
- TEMPL_SITEPATH,
- TEMPL_SITEOWNER,
- TEMPL_TITLE,
- TEMPL__MAX
-};
-
-enum gw_ref_tm {
- TM_DIFF,
- TM_LONG,
-};
-
-enum gw_tags_type {
- TAGBRIEF,
- TAGFULL,
-};
-
-static const char *const gw_templs[TEMPL__MAX] = {
- "content",
- "head",
- "header",
- "search",
- "sitepath",
- "siteowner",
- "title",
-};
-
-static const struct kvalid gw_keys[KEY__ZMAX] = {
- { kvalid_stringne, "action" },
- { kvalid_stringne, "commit" },
- { kvalid_stringne, "file" },
- { kvalid_stringne, "folder" },
- { kvalid_stringne, "headref" },
- { kvalid_int, "page" },
- { kvalid_stringne, "path" },
- { kvalid_stringne, "prev" },
-};
-
-static struct gw_header *gw_init_header(void);
-
-static void gw_free_header(struct gw_header *);
-
-static int gw_template(size_t, void *);
-
-static const struct got_error *gw_error(struct gw_trans *);
-static const struct got_error *gw_init_gw_dir(struct gw_dir **, const char *);
-static const struct got_error *gw_get_repo_description(char **,
- struct gw_trans *, char *);
-static const struct got_error *gw_get_repo_owner(char **, struct gw_trans *,
- char *);
-static const struct got_error *gw_get_time_str(char **, time_t, int);
-static const struct got_error *gw_get_repo_age(char **, struct gw_trans *,
- char *, const char *, int);
-static const struct got_error *gw_output_file_blame(struct gw_trans *,
- struct gw_header *);
-static const struct got_error *gw_output_blob_buf(struct gw_trans *,
- struct gw_header *);
-static const struct got_error *gw_output_repo_tree(struct gw_trans *,
- struct gw_header *);
-static const struct got_error *gw_output_diff(struct gw_trans *,
- struct gw_header *);
-static const struct got_error *gw_output_repo_tags(struct gw_trans *,
- struct gw_header *, int, int);
-static const struct got_error *gw_output_repo_heads(struct gw_trans *);
-static const struct got_error *gw_output_site_link(struct gw_trans *);
-static const struct got_error *gw_get_clone_url(char **, struct gw_trans *,
- char *);
-static const struct got_error *gw_colordiff_line(struct gw_trans *, char *);
-
-static const struct got_error *gw_gen_commit_header(struct gw_trans *, char *,
- char*);
-static const struct got_error *gw_gen_diff_header(struct gw_trans *, char *,
- char*);
-static const struct got_error *gw_gen_author_header(struct gw_trans *,
- const char *);
-static const struct got_error *gw_gen_age_header(struct gw_trans *,
- const char *);
-static const struct got_error *gw_gen_committer_header(struct gw_trans *,
- const char *);
-static const struct got_error *gw_gen_commit_msg_header(struct gw_trans*,
- char *);
-static const struct got_error *gw_gen_tree_header(struct gw_trans *, char *);
-static const struct got_error *gw_display_open(struct gw_trans *, enum khttp,
- enum kmime);
-static const struct got_error *gw_display_index(struct gw_trans *);
-static const struct got_error *gw_get_header(struct gw_trans *,
- struct gw_header *, int);
-static const struct got_error *gw_get_commits(struct gw_trans *,
- struct gw_header *, int,
- struct got_object_id *);
-static const struct got_error *gw_get_commit(struct gw_trans *,
- struct gw_header *,
- struct got_commit_object *,
- struct got_object_id *);
-static const struct got_error *gw_apply_unveil(const char *);
-static const struct got_error *gw_blame_cb(void *, int, int,
- struct got_commit_object *,
- struct got_object_id *);
-static const struct got_error *gw_load_got_paths(struct gw_trans *);
-static const struct got_error *gw_load_got_path(struct gw_trans *,
- struct gw_dir *);
-static const struct got_error *gw_parse_querystring(struct gw_trans *);
-static const struct got_error *gw_blame(struct gw_trans *);
-static const struct got_error *gw_blob(struct gw_trans *);
-static const struct got_error *gw_diff(struct gw_trans *);
-static const struct got_error *gw_index(struct gw_trans *);
-static const struct got_error *gw_commits(struct gw_trans *);
-static const struct got_error *gw_briefs(struct gw_trans *);
-static const struct got_error *gw_summary(struct gw_trans *);
-static const struct got_error *gw_tree(struct gw_trans *);
-static const struct got_error *gw_tag(struct gw_trans *);
-static const struct got_error *gw_tags(struct gw_trans *);
-
-struct gw_query_action {
- unsigned int func_id;
- const char *func_name;
- const struct got_error *(*func_main)(struct gw_trans *);
- const char *template;
-};
-
-enum gw_query_actions {
- GW_BLAME,
- GW_BLOB,
- GW_BRIEFS,
- GW_COMMITS,
- GW_DIFF,
- GW_ERR,
- GW_INDEX,
- GW_SUMMARY,
- GW_TAG,
- GW_TAGS,
- GW_TREE,
-};
-
-static const struct gw_query_action gw_query_funcs[] = {
- { GW_BLAME, "blame", gw_blame, "gw_tmpl/blame.tmpl" },
- { GW_BLOB, "blob", NULL, NULL },
- { GW_BRIEFS, "briefs", gw_briefs, "gw_tmpl/briefs.tmpl" },
- { GW_COMMITS, "commits", gw_commits, "gw_tmpl/commit.tmpl" },
- { GW_DIFF, "diff", gw_diff, "gw_tmpl/diff.tmpl" },
- { GW_ERR, "error", gw_error, "gw_tmpl/err.tmpl" },
- { GW_INDEX, "index", gw_index, "gw_tmpl/index.tmpl" },
- { GW_SUMMARY, "summary", gw_summary, "gw_tmpl/summry.tmpl" },
- { GW_TAG, "tag", gw_tag, "gw_tmpl/tag.tmpl" },
- { GW_TAGS, "tags", gw_tags, "gw_tmpl/tags.tmpl" },
- { GW_TREE, "tree", gw_tree, "gw_tmpl/tree.tmpl" },
-};
-
-static const char *
-gw_get_action_name(struct gw_trans *gw_trans)
-{
- return gw_query_funcs[gw_trans->action].func_name;
-}
-
-static const struct got_error *
-gw_kcgi_error(enum kcgi_err kerr)
-{
- if (kerr == KCGI_OK)
- return NULL;
-
- if (kerr == KCGI_EXIT || kerr == KCGI_HUP)
- return got_error(GOT_ERR_CANCELLED);
-
- if (kerr == KCGI_ENOMEM)
- return got_error_set_errno(ENOMEM,
- kcgi_strerror(kerr));
-
- if (kerr == KCGI_ENFILE)
- return got_error_set_errno(ENFILE,
- kcgi_strerror(kerr));
-
- if (kerr == KCGI_EAGAIN)
- return got_error_set_errno(EAGAIN,
- kcgi_strerror(kerr));
-
- if (kerr == KCGI_FORM)
- return got_error_msg(GOT_ERR_IO,
- kcgi_strerror(kerr));
-
- return got_error_from_errno(kcgi_strerror(kerr));
-}
-
-static const struct got_error *
-gw_apply_unveil(const char *repo_path)
-{
- const struct got_error *err;
-
-#ifdef PROFILE
- if (unveil("gmon.out", "rwc") != 0)
- return got_error_from_errno2("unveil", "gmon.out");
-#endif
- if (repo_path && unveil(repo_path, "r") != 0)
- return got_error_from_errno2("unveil", repo_path);
-
- if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
- return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
-
- err = got_privsep_unveil_exec_helpers();
- if (err != NULL)
- return err;
-
- if (unveil(NULL, NULL) != 0)
- return got_error_from_errno("unveil");
-
- return NULL;
-}
-
-static int
-isbinary(const uint8_t *buf, size_t n)
-{
- size_t i;
-
- for (i = 0; i < n; i++)
- if (buf[i] == 0)
- return 1;
- return 0;
-}
-
-static const struct got_error *
-gw_blame(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL;
- char *age = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- /* check querystring */
- if (gw_trans->repo_file == NULL) {
- error = got_error_msg(GOT_ERR_QUERYSTRING,
- "file required in querystring");
- goto done;
- }
- if (gw_trans->commit_id == NULL) {
- error = got_error_msg(GOT_ERR_QUERYSTRING,
- "commit required in querystring");
- goto done;
- }
-
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_header_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_header", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_get_time_str(&age, header->committer_time,
- TM_LONG);
- if (error)
- goto done;
- error = gw_gen_age_header(gw_trans, age ?age : "");
- if (error)
- goto done;
- error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_output_file_blame(gw_trans, header);
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
-done:
- gw_free_header(header);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_blob(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL, *err = NULL;
- struct gw_header *header = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- /* check querystring */
- if (gw_trans->repo_file == NULL) {
- error = got_error_msg(GOT_ERR_QUERYSTRING,
- "file required in querystring");
- goto done;
- }
- if (gw_trans->commit_id == NULL) {
- error = got_error_msg(GOT_ERR_QUERYSTRING,
- "commit required in querystring");
- goto done;
- }
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
-
- error = gw_output_blob_buf(gw_trans, header);
-done:
- if (error) {
- gw_trans->mime = KMIME_TEXT_PLAIN;
- err = gw_display_index(gw_trans);
- if (err) {
- error = err;
- goto errored;
- }
- kerr = khttp_puts(gw_trans->gw_req, error->msg);
- }
-errored:
- gw_free_header(header);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_diff(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL;
- char *age = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "diff_header_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "diff_header", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_gen_diff_header(gw_trans, header->parent_id,
- header->commit_id);
- if (error)
- goto done;
- error = gw_gen_commit_header(gw_trans, header->commit_id,
- header->refs_str);
- if (error)
- goto done;
- error = gw_gen_tree_header(gw_trans, header->tree_id);
- if (error)
- goto done;
- error = gw_gen_author_header(gw_trans, header->author);
- if (error)
- goto done;
- error = gw_gen_committer_header(gw_trans, header->author);
- if (error)
- goto done;
- error = gw_get_time_str(&age, header->committer_time,
- TM_LONG);
- if (error)
- goto done;
- error = gw_gen_age_header(gw_trans, age ?age : "");
- if (error)
- goto done;
- error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "diff", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_output_diff(gw_trans, header);
- if (error)
- goto done;
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- gw_free_header(header);
- free(age);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_index(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_dir *gw_dir = NULL;
- char *href_next = NULL, *href_prev = NULL, *href_summary = NULL;
- char *href_briefs = NULL, *href_commits = NULL, *href_tree = NULL;
- char *href_tags = NULL;
- unsigned int prev_disp = 0, next_disp = 1, dir_c = 0;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1) {
- error = got_error_from_errno("pledge");
- return error;
- }
-#endif
- error = gw_apply_unveil(gw_trans->gw_conf->got_repos_path);
- if (error)
- return error;
-
- error = gw_load_got_paths(gw_trans);
- if (error)
- return error;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_header", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_header_project", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_puts(gw_trans->gw_html_req, "Project");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (gw_trans->gw_conf->got_show_repo_description) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_header_description", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_puts(gw_trans->gw_html_req, "Description");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- if (gw_trans->gw_conf->got_show_repo_owner) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_header_owner", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_puts(gw_trans->gw_html_req, "Owner");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- if (gw_trans->gw_conf->got_show_repo_age) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_header_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_puts(gw_trans->gw_html_req, "Last Change");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (TAILQ_EMPTY(&gw_trans->gw_dirs)) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_printf(gw_trans->gw_html_req,
- "No repositories found in %s",
- gw_trans->gw_conf->got_repos_path);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- return error;
- }
-
- TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry)
- dir_c++;
-
- TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry) {
- if (gw_trans->page > 0 && (gw_trans->page *
- gw_trans->gw_conf->got_max_repos_display) > prev_disp) {
- prev_disp++;
- continue;
- }
-
- prev_disp++;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- href_summary = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_dir->name, "action", "summary", NULL);
- if (href_summary == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "index_project", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_summary, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, gw_dir->name);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- if (gw_trans->gw_conf->got_show_repo_description) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "index_project_description", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_dir->description ? gw_dir->description : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
- if (gw_trans->gw_conf->got_show_repo_owner) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "index_project_owner", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_dir->owner ? gw_dir->owner : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
- if (gw_trans->gw_conf->got_show_repo_age) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "index_project_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_dir->age ? gw_dir->age : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "navs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "navs", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_summary, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "summary");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_briefs = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_dir->name, "action", "briefs", NULL);
- if (href_briefs == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_briefs, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "commit briefs");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_commits = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_dir->name, "action", "commits", NULL);
- if (href_commits == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_commits, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "commits");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_tags = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_dir->name, "action", "tags", NULL);
- if (href_tags == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_tags, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "tags");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_tree = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_dir->name, "action", "tree", NULL);
- if (href_tree == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_tree, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "tree");
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 4);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- free(href_summary);
- href_summary = NULL;
- free(href_briefs);
- href_briefs = NULL;
- free(href_commits);
- href_commits = NULL;
- free(href_tags);
- href_tags = NULL;
- free(href_tree);
- href_tree = NULL;
-
- if (gw_trans->gw_conf->got_max_repos_display == 0)
- continue;
-
- if ((next_disp == gw_trans->gw_conf->got_max_repos_display) ||
- ((gw_trans->gw_conf->got_max_repos_display > 0) &&
- (gw_trans->page > 0) &&
- (next_disp == gw_trans->gw_conf->got_max_repos_display ||
- prev_disp == gw_trans->repos_total))) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "np_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_prev", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
- (gw_trans->page > 0) &&
- (next_disp == gw_trans->gw_conf->got_max_repos_display ||
- prev_disp == gw_trans->repos_total)) {
- href_prev = khttp_urlpartx(NULL, NULL, "gotweb", "page",
- KATTRX_INT, (int64_t)(gw_trans->page - 1), NULL);
- if (href_prev == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_prev, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Previous");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (gw_trans->gw_conf->got_max_repos_display > 0 &&
- next_disp == gw_trans->gw_conf->got_max_repos_display &&
- dir_c != (gw_trans->page + 1) *
- gw_trans->gw_conf->got_max_repos_display) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_next", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- href_next = khttp_urlpartx(NULL, NULL, "gotweb", "page",
- KATTRX_INT, (int64_t)(gw_trans->page + 1), NULL);
- if (href_next == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_next, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Next");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
- next_disp = 0;
- break;
- }
-
- if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
- (gw_trans->page > 0) &&
- (next_disp == gw_trans->gw_conf->got_max_repos_display ||
- prev_disp == gw_trans->repos_total)) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- }
- next_disp++;
- }
-done:
- free(href_prev);
- free(href_next);
- free(href_summary);
- free(href_briefs);
- free(href_commits);
- free(href_tags);
- free(href_tree);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_commits(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL, *n_header = NULL;
- char *age = NULL, *href_diff = NULL, *href_tree = NULL;
- char *href_prev = NULL, *href_next = NULL;
- enum kcgi_err kerr = KCGI_OK;
- int commit_found = 0;
-
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1) {
- error = got_error_from_errno("pledge");
- goto done;
- }
-#endif
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- error = gw_get_header(gw_trans, header,
- gw_trans->gw_conf->got_max_commits_display);
- if (error)
- goto done;
-
- TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
- if (commit_found == 0 && gw_trans->commit_id != NULL) {
- if (strcmp(gw_trans->commit_id,
- n_header->commit_id) != 0)
- continue;
- else
- commit_found = 1;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "commits_line_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_gen_commit_header(gw_trans, n_header->commit_id,
- n_header->refs_str);
- if (error)
- goto done;
- error = gw_gen_author_header(gw_trans, n_header->author);
- if (error)
- goto done;
- error = gw_gen_committer_header(gw_trans, n_header->author);
- if (error)
- goto done;
- error = gw_get_time_str(&age, n_header->committer_time,
- TM_LONG);
- if (error)
- goto done;
- error = gw_gen_age_header(gw_trans, age ?age : "");
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "commit", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khttp_puts(gw_trans->gw_req, n_header->commit_msg);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- href_diff = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "diff", "commit",
- n_header->commit_id, NULL);
- if (href_diff == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_diff, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "diff");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_tree = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "tree", "commit",
- n_header->commit_id, NULL);
- if (href_tree == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_tree, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- khtml_puts(gw_trans->gw_html_req, "tree");
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "solid_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
-
- free(age);
- age = NULL;
- }
-
- if (gw_trans->next_id || gw_trans->prev_id) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "np_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_prev", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->prev_id) {
- href_prev = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page - 1), "action",
- KATTRX_STRING, "commits", "commit", KATTRX_STRING,
- gw_trans->prev_id ? gw_trans->prev_id : "", NULL);
- if (href_prev == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_prev, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Previous");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- if (gw_trans->next_id) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_next", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- href_next = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page + 1), "action",
- KATTRX_STRING, "commits", "commit", KATTRX_STRING,
- gw_trans->next_id, NULL);
- if (href_next == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_next, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Next");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- }
-done:
- gw_free_header(header);
- TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
- gw_free_header(n_header);
- free(age);
- free(href_next);
- free(href_prev);
- free(href_diff);
- free(href_tree);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_briefs(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL, *n_header = NULL;
- char *age = NULL, *href_diff = NULL, *href_tree = NULL;
- char *href_prev = NULL, *href_next = NULL;
- char *newline, *smallerthan;
- enum kcgi_err kerr = KCGI_OK;
- int commit_found = 0;
-
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1) {
- error = got_error_from_errno("pledge");
- goto done;
- }
-#endif
- if (gw_trans->action != GW_SUMMARY) {
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
- }
-
- if (gw_trans->action == GW_SUMMARY)
- error = gw_get_header(gw_trans, header, D_MAXSLCOMMDISP);
- else
- error = gw_get_header(gw_trans, header,
- gw_trans->gw_conf->got_max_commits_display);
- if (error)
- goto done;
-
- TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
- if (commit_found == 0 && gw_trans->commit_id != NULL) {
- if (strcmp(gw_trans->commit_id,
- n_header->commit_id) != 0)
- continue;
- else
- commit_found = 1;
- }
- error = gw_get_time_str(&age, n_header->committer_time,
- TM_DIFF);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "briefs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "briefs_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, age ? age : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "briefs_author", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- smallerthan = strchr(n_header->author, '<');
- if (smallerthan)
- *smallerthan = '\0';
- kerr = khtml_puts(gw_trans->gw_html_req, n_header->author);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- href_diff = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "diff", "commit",
- n_header->commit_id, NULL);
- if (href_diff == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "briefs_log", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- newline = strchr(n_header->commit_msg, '\n');
- if (newline)
- *newline = '\0';
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_diff, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, n_header->commit_msg);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- if (n_header->refs_str) {
- kerr = khtml_puts(gw_trans->gw_html_req, " ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_SPAN,
- KATTR_ID, "refs_str", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, "(%s)",
- n_header->refs_str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_diff, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "diff");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_tree = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "tree", "commit",
- n_header->commit_id, NULL);
- if (href_tree == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_tree, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- khtml_puts(gw_trans->gw_html_req, "tree");
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
-
- free(age);
- age = NULL;
- free(href_diff);
- href_diff = NULL;
- free(href_tree);
- href_tree = NULL;
- }
-
- if (gw_trans->next_id || gw_trans->prev_id) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "np_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_prev", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->prev_id) {
- href_prev = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page - 1), "action",
- KATTRX_STRING, "briefs", "commit", KATTRX_STRING,
- gw_trans->prev_id ? gw_trans->prev_id : "", NULL);
- if (href_prev == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_prev, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Previous");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- if (gw_trans->next_id) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_next", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- href_next = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page + 1), "action",
- KATTRX_STRING, "briefs", "commit", KATTRX_STRING,
- gw_trans->next_id, NULL);
- if (href_next == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_next, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Next");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- }
-done:
- gw_free_header(header);
- TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
- gw_free_header(n_header);
- free(age);
- free(href_next);
- free(href_prev);
- free(href_diff);
- free(href_tree);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_summary(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- char *age = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "summary_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (gw_trans->gw_conf->got_show_repo_description &&
- gw_trans->gw_dir->description != NULL &&
- (strcmp(gw_trans->gw_dir->description, "") != 0)) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "description_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Description: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "description", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_trans->gw_dir->description);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->gw_conf->got_show_repo_owner &&
- gw_trans->gw_dir->owner != NULL &&
- (strcmp(gw_trans->gw_dir->owner, "") != 0)) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "repo_owner_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Owner: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "repo_owner", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_trans->gw_dir->owner);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->gw_conf->got_show_repo_age) {
- error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
- NULL, TM_LONG);
- if (error)
- goto done;
- if (age != NULL) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "last_change_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- "Last Change: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "last_change", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, age);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
- }
-
- if (gw_trans->gw_conf->got_show_repo_cloneurl &&
- gw_trans->gw_dir->url != NULL &&
- (strcmp(gw_trans->gw_dir->url, "") != 0)) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "cloneurl_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Clone URL: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "cloneurl", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, gw_trans->gw_dir->url);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "briefs_title_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "briefs_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Commit Briefs");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_briefs(gw_trans);
- if (error)
- goto done;
-
- error = gw_tags(gw_trans);
- if (error)
- goto done;
-
- error = gw_output_repo_heads(gw_trans);
-done:
- free(age);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_tree(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL;
- char *tree = NULL, *tree_html = NULL, *tree_html_disp = NULL;
- char *age = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tree_header_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tree_header", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_gen_tree_header(gw_trans, header->tree_id);
- if (error)
- goto done;
- error = gw_get_time_str(&age, header->committer_time,
- TM_LONG);
- if (error)
- goto done;
- error = gw_gen_age_header(gw_trans, age ?age : "");
- if (error)
- goto done;
- error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tree", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_output_repo_tree(gw_trans, header);
- if (error)
- goto done;
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- gw_free_header(header);
- free(tree_html_disp);
- free(tree_html);
- free(tree);
- free(age);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_tags(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL;
- char *href_next = NULL, *href_prev = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
- NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- if (gw_trans->action != GW_SUMMARY) {
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
- }
-
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
-
- if (gw_trans->action == GW_SUMMARY) {
- gw_trans->next_id = NULL;
- error = gw_output_repo_tags(gw_trans, header,
- D_MAXSLCOMMDISP, TAGBRIEF);
- if (error)
- goto done;
- } else {
- error = gw_output_repo_tags(gw_trans, header,
- gw_trans->gw_conf->got_max_commits_display, TAGBRIEF);
- if (error)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "np_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_prev", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->prev_id) {
- href_prev = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page - 1), "action",
- KATTRX_STRING, "tags", "commit", KATTRX_STRING,
- gw_trans->prev_id ? gw_trans->prev_id : "", NULL);
- if (href_prev == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_prev, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Previous");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- if (gw_trans->next_id) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "nav_next", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- href_next = khttp_urlpartx(NULL, NULL, "gotweb", "path",
- KATTRX_STRING, gw_trans->repo_name, "page",
- KATTRX_INT, (int64_t) (gw_trans->page + 1), "action",
- KATTRX_STRING, "tags", "commit", KATTRX_STRING,
- gw_trans->next_id, NULL);
- if (href_next == NULL) {
- error = got_error_from_errno("khttp_urlpartx");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_next, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Next");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
- }
-
- if (gw_trans->next_id || gw_trans->page > 0) {
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- }
-done:
- gw_free_header(header);
- free(href_next);
- free(href_prev);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_tag(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct gw_header *header = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
-#ifndef PROFILE
- if (pledge("stdio rpath wpath cpath proc exec sendfd unveil", NULL) == -1)
- return got_error_from_errno("pledge");
-#endif
- if ((header = gw_init_header()) == NULL)
- return got_error_from_errno("malloc");
-
- error = gw_apply_unveil(gw_trans->gw_dir->path);
- if (error)
- goto done;
-
- if (gw_trans->commit_id == NULL) {
- error = got_error_msg(GOT_ERR_QUERYSTRING,
- "commit required in querystring");
- goto done;
- }
-
- error = gw_get_header(gw_trans, header, 1);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tag_header_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tag_header", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_gen_commit_header(gw_trans, header->commit_id,
- header->refs_str);
- if (error)
- goto done;
- error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
- if (error)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tree", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- error = gw_output_repo_tags(gw_trans, header, 1, TAGFULL);
- if (error)
- goto done;
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- gw_free_header(header);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_load_got_path(struct gw_trans *gw_trans, struct gw_dir *gw_dir)
-{
- const struct got_error *error = NULL;
- DIR *dt;
- char *dir_test;
- int opened = 0;
-
- if (asprintf(&dir_test, "%s/%s/%s",
- gw_trans->gw_conf->got_repos_path, gw_dir->name,
- GOTWEB_GIT_DIR) == -1)
- return got_error_from_errno("asprintf");
-
- dt = opendir(dir_test);
- if (dt == NULL) {
- free(dir_test);
- } else {
- gw_dir->path = strdup(dir_test);
- if (gw_dir->path == NULL) {
- opened = 1;
- error = got_error_from_errno("strdup");
- goto errored;
- }
- opened = 1;
- goto done;
- }
-
- if (asprintf(&dir_test, "%s/%s/%s",
- gw_trans->gw_conf->got_repos_path, gw_dir->name,
- GOTWEB_GOT_DIR) == -1) {
- dir_test = NULL;
- error = got_error_from_errno("asprintf");
- goto errored;
- }
-
- dt = opendir(dir_test);
- if (dt == NULL)
- free(dir_test);
- else {
- opened = 1;
- error = got_error(GOT_ERR_NOT_GIT_REPO);
- goto errored;
- }
-
- if (asprintf(&dir_test, "%s/%s",
- gw_trans->gw_conf->got_repos_path, gw_dir->name) == -1) {
- error = got_error_from_errno("asprintf");
- dir_test = NULL;
- goto errored;
- }
-
- gw_dir->path = strdup(dir_test);
- if (gw_dir->path == NULL) {
- opened = 1;
- error = got_error_from_errno("strdup");
- goto errored;
- }
-
- dt = opendir(dir_test);
- if (dt == NULL) {
- error = got_error_path(gw_dir->name, GOT_ERR_NOT_GIT_REPO);
- goto errored;
- } else
- opened = 1;
-done:
- error = gw_get_repo_description(&gw_dir->description, gw_trans,
- gw_dir->path);
- if (error)
- goto errored;
- error = gw_get_repo_owner(&gw_dir->owner, gw_trans, gw_dir->path);
- if (error)
- goto errored;
- error = gw_get_repo_age(&gw_dir->age, gw_trans, gw_dir->path,
- NULL, TM_DIFF);
- if (error)
- goto errored;
- error = gw_get_clone_url(&gw_dir->url, gw_trans, gw_dir->path);
-errored:
- free(dir_test);
- if (opened)
- if (dt && closedir(dt) == -1 && error == NULL)
- error = got_error_from_errno("closedir");
- return error;
-}
-
-static const struct got_error *
-gw_load_got_paths(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- DIR *d;
- struct dirent **sd_dent;
- struct gw_dir *gw_dir;
- struct stat st;
- unsigned int d_cnt, d_i;
-
- d = opendir(gw_trans->gw_conf->got_repos_path);
- if (d == NULL) {
- error = got_error_from_errno2("opendir",
- gw_trans->gw_conf->got_repos_path);
- return error;
- }
-
- d_cnt = scandir(gw_trans->gw_conf->got_repos_path, &sd_dent, NULL,
- alphasort);
- if (d_cnt == -1) {
- error = got_error_from_errno2("scandir",
- gw_trans->gw_conf->got_repos_path);
- goto done;
- }
-
- for (d_i = 0; d_i < d_cnt; d_i++) {
- if (gw_trans->gw_conf->got_max_repos > 0 &&
- (d_i - 2) == gw_trans->gw_conf->got_max_repos)
- break; /* account for parent and self */
-
- if (strcmp(sd_dent[d_i]->d_name, ".") == 0 ||
- strcmp(sd_dent[d_i]->d_name, "..") == 0)
- continue;
-
- error = gw_init_gw_dir(&gw_dir, sd_dent[d_i]->d_name);
- if (error)
- goto done;
-
- error = gw_load_got_path(gw_trans, gw_dir);
- if (error && error->code == GOT_ERR_NOT_GIT_REPO) {
- error = NULL;
- continue;
- } else if (error && error->code != GOT_ERR_LONELY_PACKIDX)
- goto done;
-
- if (lstat(gw_dir->path, &st) == 0 && S_ISDIR(st.st_mode) &&
- !got_path_dir_is_empty(gw_dir->path)) {
- TAILQ_INSERT_TAIL(&gw_trans->gw_dirs, gw_dir,
- entry);
- gw_trans->repos_total++;
- }
- }
-done:
- if (d && closedir(d) == -1 && error == NULL)
- error = got_error_from_errno("closedir");
- return error;
-}
-
-static const struct got_error *
-gw_parse_querystring(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct kpair *p;
- const struct gw_query_action *action = NULL;
- unsigned int i;
-
- if (gw_trans->gw_req->fieldnmap[0]) {
- return got_error(GOT_ERR_QUERYSTRING);
- } else if ((p = gw_trans->gw_req->fieldmap[KEY_PATH])) {
- /* define gw_trans->repo_path */
- gw_trans->repo_name = p->parsed.s;
-
- if (asprintf(&gw_trans->repo_path, "%s/%s",
- gw_trans->gw_conf->got_repos_path, p->parsed.s) == -1)
- return got_error_from_errno("asprintf");
-
- /* get action and set function */
- if ((p = gw_trans->gw_req->fieldmap[KEY_ACTION])) {
- for (i = 0; i < nitems(gw_query_funcs); i++) {
- action = &gw_query_funcs[i];
- if (action->func_name == NULL)
- continue;
- if (strcmp(action->func_name,
- p->parsed.s) == 0) {
- gw_trans->action = i;
- break;
- }
- }
- }
- if (gw_trans->action == -1) {
- gw_trans->action = GW_ERR;
- gw_trans->error = got_error_msg(GOT_ERR_QUERYSTRING,
- p != NULL ? "bad action in querystring" :
- "no action in querystring");
- return error;
- }
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_COMMIT_ID])) {
- if (asprintf(&gw_trans->commit_id, "%s",
- p->parsed.s) == -1)
- return got_error_from_errno("asprintf");
- }
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_FILE]))
- gw_trans->repo_file = p->parsed.s;
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_FOLDER])) {
- if (asprintf(&gw_trans->repo_folder, "%s",
- p->parsed.s) == -1)
- return got_error_from_errno("asprintf");
- }
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_PREV_ID])) {
- if (asprintf(&gw_trans->prev_id, "%s",
- p->parsed.s) == -1)
- return got_error_from_errno("asprintf");
- }
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_HEADREF]))
- gw_trans->headref = p->parsed.s;
-
- error = gw_init_gw_dir(&gw_trans->gw_dir, gw_trans->repo_name);
- if (error)
- return error;
-
- gw_trans->error = gw_load_got_path(gw_trans, gw_trans->gw_dir);
- } else
- gw_trans->action = GW_INDEX;
-
- if ((p = gw_trans->gw_req->fieldmap[KEY_PAGE]))
- gw_trans->page = p->parsed.i;
-
- return error;
-}
-
-static const struct got_error *
-gw_init_gw_dir(struct gw_dir **gw_dir, const char *dir)
-{
- const struct got_error *error;
-
- *gw_dir = malloc(sizeof(**gw_dir));
- if (*gw_dir == NULL)
- return got_error_from_errno("malloc");
-
- if (asprintf(&(*gw_dir)->name, "%s", dir) == -1) {
- error = got_error_from_errno("asprintf");
- free(*gw_dir);
- *gw_dir = NULL;
- return error;
- }
-
- return NULL;
-}
-
-static const struct got_error *
-gw_display_open(struct gw_trans *gw_trans, enum khttp code, enum kmime mime)
-{
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_ALLOW], "GET");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_STATUS], "%s",
- khttps[code]);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_CONTENT_TYPE], "%s",
- kmimetypes[mime]);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khttp_head(gw_trans->gw_req, "X-Content-Type-Options",
- "nosniff");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khttp_head(gw_trans->gw_req, "X-Frame-Options", "DENY");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- kerr = khttp_head(gw_trans->gw_req, "X-XSS-Protection",
- "1; mode=block");
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (gw_trans->mime == KMIME_APP_OCTET_STREAM) {
- kerr = khttp_head(gw_trans->gw_req,
- kresps[KRESP_CONTENT_DISPOSITION],
- "attachment; filename=%s", gw_trans->repo_file);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
- }
-
- kerr = khttp_body(gw_trans->gw_req);
- return gw_kcgi_error(kerr);
-}
-
-static const struct got_error *
-gw_display_index(struct gw_trans *gw_trans)
-{
- const struct got_error *error;
- enum kcgi_err kerr = KCGI_OK;
-
- /* catch early querystring errors */
- if (gw_trans->error)
- gw_trans->action = GW_ERR;
-
- error = gw_display_open(gw_trans, KHTTP_200, gw_trans->mime);
- if (error)
- return error;
-
- kerr = khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0);
- if (kerr != KCGI_OK)
- return gw_kcgi_error(kerr);
-
- if (gw_trans->action != GW_BLOB) {
- kerr = khttp_template(gw_trans->gw_req, gw_trans->gw_tmpl,
- gw_query_funcs[gw_trans->action].template);
- if (kerr != KCGI_OK) {
- khtml_close(gw_trans->gw_html_req);
- return gw_kcgi_error(kerr);
- }
- }
-
- return gw_kcgi_error(khtml_close(gw_trans->gw_html_req));
-}
-
-static const struct got_error *
-gw_error(struct gw_trans *gw_trans)
-{
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_puts(gw_trans->gw_html_req, gw_trans->error->msg);
-
- return gw_kcgi_error(kerr);
-}
-
-static int
-gw_template(size_t key, void *arg)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
- struct gw_trans *gw_trans = arg;
- char *ati = NULL, *fic32 = NULL, *fic16 = NULL;
- char *swm = NULL, *spt = NULL, *css = NULL, *logo = NULL;
-
- if (asprintf(&ati, "%s%s", gw_trans->gw_conf->got_www_path,
- "/apple-touch-icon.png") == -1)
- goto err;
- if (asprintf(&fic32, "%s%s", gw_trans->gw_conf->got_www_path,
- "/favicon-32x32.png") == -1)
- goto err;
- if (asprintf(&fic16, "%s%s", gw_trans->gw_conf->got_www_path,
- "/favicon-16x16.png") == -1)
- goto err;
- if (asprintf(&swm, "%s%s", gw_trans->gw_conf->got_www_path,
- "/site.webmanifest") == -1)
- goto err;
- if (asprintf(&spt, "%s%s", gw_trans->gw_conf->got_www_path,
- "/safari-pinned-tab.svg") == -1)
- goto err;
- if (asprintf(&css, "%s%s", gw_trans->gw_conf->got_www_path,
- "/gotweb.css") == -1)
- goto err;
- if (asprintf(&logo, "%s%s%s", gw_trans->gw_conf->got_www_path,
- gw_trans->gw_conf->got_www_path ? "/" : "",
- gw_trans->gw_conf->got_logo) == -1)
- goto err;
-
- switch (key) {
- case (TEMPL_HEAD):
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_META,
- KATTR_NAME, "viewport",
- KATTR_CONTENT, "initial-scale=.75, user-scalable=yes",
- KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_META,
- KATTR_CHARSET, "utf-8",
- KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_META,
- KATTR_NAME, "msapplication-TileColor",
- KATTR_CONTENT, "#da532c", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_META,
- KATTR_NAME, "theme-color",
- KATTR_CONTENT, "#ffffff", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "apple-touch-icon", KATTR_SIZES, "180x180",
- KATTR_HREF, ati, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "icon", KATTR_TYPE, "image/png", KATTR_SIZES,
- "32x32", KATTR_HREF, fic32, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "icon", KATTR_TYPE, "image/png", KATTR_SIZES,
- "16x16", KATTR_HREF, fic16, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "manifest", KATTR_HREF, swm,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "mask-icon", KATTR_HREF,
- spt, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_LINK,
- KATTR_REL, "stylesheet", KATTR_TYPE, "text/css",
- KATTR_HREF, css, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- break;
- case(TEMPL_HEADER):
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "got_link", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, gw_trans->gw_conf->got_logo_url,
- KATTR_TARGET, "_sotd", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_IMG,
- KATTR_SRC, logo, KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- return 0;
- break;
- case (TEMPL_SITEPATH):
- error = gw_output_site_link(gw_trans);
- if (error)
- return 0;
- break;
- case(TEMPL_TITLE):
- if (gw_trans->gw_conf->got_site_name != NULL) {
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_trans->gw_conf->got_site_name);
- if (kerr != KCGI_OK)
- return 0;
- }
- break;
- case (TEMPL_SEARCH):
- break;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "search", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_FORM,
- KATTR_METHOD, "POST", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_INPUT, KATTR_ID,
- "got-search", KATTR_NAME, "got-search", KATTR_SIZE, "15",
- KATTR_MAXLENGTH, "50", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_BUTTON,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_puts(gw_trans->gw_html_req, "Search");
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 4);
- if (kerr != KCGI_OK)
- return 0;
- break;
- case(TEMPL_SITEOWNER):
- if (gw_trans->gw_conf->got_site_owner != NULL &&
- gw_trans->gw_conf->got_show_site_owner) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "site_owner_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "site_owner", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_trans->gw_conf->got_site_owner);
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- return 0;
- }
- break;
- case(TEMPL_CONTENT):
- error = gw_query_funcs[gw_trans->action].func_main(gw_trans);
- if (error) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tmpl_err", KATTR__MAX);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khttp_printf(gw_trans->gw_req, "Error: %s",
- error->msg);
- if (kerr != KCGI_OK)
- return 0;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- return 0;
- }
- break;
- default:
- return 0;
- }
- free(ati);
- free(fic32);
- free(fic16);
- free(swm);
- free(spt);
- free(css);
- free(logo);
- return 1;
-err:
- free(ati);
- free(fic32);
- free(fic16);
- free(swm);
- free(spt);
- free(css);
- free(logo);
- return 0;
-}
-
-static const struct got_error *
-gw_gen_commit_header(struct gw_trans *gw_trans, char *str1, char *str2)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_commit_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Commit: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_commit", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, "%s ", str1);
- if (kerr != KCGI_OK)
- goto done;
- if (str2 != NULL) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_SPAN,
- KATTR_ID, "refs_str", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, "(%s)", str2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_diff_header(struct gw_trans *gw_trans, char *str1, char *str2)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_diff_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Diff: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_diff", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- if (str1 != NULL) {
- kerr = khtml_puts(gw_trans->gw_html_req, str1);
- if (kerr != KCGI_OK)
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_BR, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, str2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_age_header(struct gw_trans *gw_trans, const char *str)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_age_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Date: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_author_header(struct gw_trans *gw_trans, const char *str)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_author_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Author: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_author", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_committer_header(struct gw_trans *gw_trans, const char *str)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_committer_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Committer: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_committer", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_commit_msg_header(struct gw_trans *gw_trans, char *str)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_commit_msg_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Message: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_commit_msg", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khttp_puts(gw_trans->gw_req, str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_gen_tree_header(struct gw_trans *gw_trans, char *str)
-{
- const struct got_error *error = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_tree_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Tree: ");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "header_tree", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, str);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
-done:
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_get_repo_description(char **description, struct gw_trans *gw_trans,
- char *dir)
-{
- const struct got_error *error = NULL;
- FILE *f = NULL;
- char *d_file = NULL;
- unsigned int len;
- size_t n;
-
- *description = NULL;
- if (gw_trans->gw_conf->got_show_repo_description == 0)
- return NULL;
-
- if (asprintf(&d_file, "%s/description", dir) == -1)
- return got_error_from_errno("asprintf");
-
- f = fopen(d_file, "re");
- if (f == NULL) {
- if (errno == ENOENT || errno == EACCES)
- return NULL;
- error = got_error_from_errno2("fopen", d_file);
- goto done;
- }
-
- if (fseek(f, 0, SEEK_END) == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
- len = ftell(f);
- if (len == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
- if (fseek(f, 0, SEEK_SET) == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
- *description = calloc(len + 1, sizeof(**description));
- if (*description == NULL) {
- error = got_error_from_errno("calloc");
- goto done;
- }
-
- n = fread(*description, 1, len, f);
- if (n == 0 && ferror(f))
- error = got_ferror(f, GOT_ERR_IO);
-done:
- if (f != NULL && fclose(f) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- free(d_file);
- return error;
-}
-
-static const struct got_error *
-gw_get_time_str(char **repo_age, time_t committer_time, int ref_tm)
-{
- struct tm tm;
- time_t diff_time;
- const char *years = "years ago", *months = "months ago";
- const char *weeks = "weeks ago", *days = "days ago", *hours = "hours ago";
- const char *minutes = "minutes ago", *seconds = "seconds ago";
- const char *now = "right now";
- const char *s;
- char datebuf[29];
-
- *repo_age = NULL;
-
- switch (ref_tm) {
- case TM_DIFF:
- diff_time = time(NULL) - committer_time;
- if (diff_time > 60 * 60 * 24 * 365 * 2) {
- if (asprintf(repo_age, "%lld %s",
- (diff_time / 60 / 60 / 24 / 365), years) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 60 * 60 * 24 * (365 / 12) * 2) {
- if (asprintf(repo_age, "%lld %s",
- (diff_time / 60 / 60 / 24 / (365 / 12)),
- months) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 60 * 60 * 24 * 7 * 2) {
- if (asprintf(repo_age, "%lld %s",
- (diff_time / 60 / 60 / 24 / 7), weeks) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 60 * 60 * 24 * 2) {
- if (asprintf(repo_age, "%lld %s",
- (diff_time / 60 / 60 / 24), days) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 60 * 60 * 2) {
- if (asprintf(repo_age, "%lld %s",
- (diff_time / 60 / 60), hours) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 60 * 2) {
- if (asprintf(repo_age, "%lld %s", (diff_time / 60),
- minutes) == -1)
- return got_error_from_errno("asprintf");
- } else if (diff_time > 2) {
- if (asprintf(repo_age, "%lld %s", diff_time,
- seconds) == -1)
- return got_error_from_errno("asprintf");
- } else {
- if (asprintf(repo_age, "%s", now) == -1)
- return got_error_from_errno("asprintf");
- }
- break;
- case TM_LONG:
- if (gmtime_r(&committer_time, &tm) == NULL)
- return got_error_from_errno("gmtime_r");
-
- s = asctime_r(&tm, datebuf);
- if (s == NULL)
- return got_error_from_errno("asctime_r");
-
- if (asprintf(repo_age, "%s UTC", datebuf) == -1)
- return got_error_from_errno("asprintf");
- break;
- }
- return NULL;
-}
-
-static const struct got_error *
-gw_get_repo_age(char **repo_age, struct gw_trans *gw_trans, char *dir,
- const char *refname, int ref_tm)
-{
- const struct got_error *error = NULL;
- struct got_repository *repo = NULL;
- struct got_commit_object *commit = NULL;
- struct got_reflist_head refs;
- struct got_reflist_entry *re;
- time_t committer_time = 0, cmp_time = 0;
-
- *repo_age = NULL;
- TAILQ_INIT(&refs);
-
- if (gw_trans->gw_conf->got_show_repo_age == 0)
- return NULL;
-
- if (gw_trans->repo)
- repo = gw_trans->repo;
- else {
- error = got_repo_open(&repo, dir, NULL, gw_trans->pack_fds);
- if (error)
- return error;
- }
-
- error = got_ref_list(&refs, repo, "refs/heads",
- got_ref_cmp_by_name, NULL);
- if (error)
- goto done;
-
- /*
- * Find the youngest branch tip in the repository, or the age of
- * the a specific branch tip if a name was provided by the caller.
- */
- TAILQ_FOREACH(re, &refs, entry) {
- struct got_object_id *id = NULL;
-
- if (refname && strcmp(got_ref_get_name(re->ref), refname) != 0)
- continue;
-
- error = got_ref_resolve(&id, repo, re->ref);
- if (error)
- goto done;
-
- error = got_object_open_as_commit(&commit, repo, id);
- free(id);
- if (error)
- goto done;
-
- committer_time =
- got_object_commit_get_committer_time(commit);
- got_object_commit_close(commit);
- if (cmp_time < committer_time)
- cmp_time = committer_time;
-
- if (refname)
- break;
- }
-
- if (cmp_time != 0) {
- committer_time = cmp_time;
- error = gw_get_time_str(repo_age, committer_time, ref_tm);
- }
-done:
- got_ref_list_free(&refs);
- if (gw_trans->repo == NULL) {
- const struct got_error *close_err = got_repo_close(repo);
- if (error == NULL)
- error = close_err;
- }
- return error;
-}
-
-static const struct got_error *
-gw_output_diff(struct gw_trans *gw_trans, struct gw_header *header)
-{
- const struct got_error *error;
- FILE *f = NULL, *f1 = NULL, *f2 = NULL;
- int fd1 = -1, fd2 = -1;
- struct got_object_id *id1 = NULL, *id2 = NULL;
- char *label1 = NULL, *label2 = NULL, *line = NULL;
- int obj_type;
- size_t linesize = 0;
- ssize_t linelen;
- enum kcgi_err kerr = KCGI_OK;
-
- f = got_opentemp();
- if (f == NULL)
- return NULL;
-
- f1 = got_opentemp();
- if (f1 == NULL) {
- error = got_error_from_errno("got_opentemp");
- goto done;
- }
-
- f2 = got_opentemp();
- if (f2 == NULL) {
- error = got_error_from_errno("got_opentemp");
- goto done;
- }
-
- fd1 = got_opentempfd();
- if (fd1 == -1) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
-
- fd2 = got_opentempfd();
- if (fd2 == -1) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
-
- if (header->parent_id != NULL &&
- strncmp(header->parent_id, "/dev/null", 9) != 0) {
- error = got_repo_match_object_id(&id1, &label1,
- header->parent_id, GOT_OBJ_TYPE_ANY,
- &header->refs, gw_trans->repo);
- if (error)
- goto done;
- }
-
- error = got_repo_match_object_id(&id2, &label2,
- header->commit_id, GOT_OBJ_TYPE_ANY, &header->refs,
- gw_trans->repo);
- if (error)
- goto done;
-
- error = got_object_get_type(&obj_type, gw_trans->repo, id2);
- if (error)
- goto done;
- switch (obj_type) {
- case GOT_OBJ_TYPE_BLOB:
- error = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
- fd1, fd2, id1, id2, NULL, NULL, GOT_DIFF_ALGORITHM_PATIENCE,
- 3, 0, 0, gw_trans->repo, f);
- break;
- case GOT_OBJ_TYPE_TREE:
- error = got_diff_objects_as_trees(NULL, NULL, f1, f2,
- fd1, fd2, id1, id2, NULL, "", "",
- GOT_DIFF_ALGORITHM_PATIENCE, 3, 0, 0, gw_trans->repo, f);
- break;
- case GOT_OBJ_TYPE_COMMIT:
- error = got_diff_objects_as_commits(NULL, NULL, f1, f2,
- fd1, fd2, id1, id2, NULL, GOT_DIFF_ALGORITHM_PATIENCE,
- 3, 0, 0, gw_trans->repo, f);
- break;
- default:
- error = got_error(GOT_ERR_OBJ_TYPE);
- }
- if (error)
- goto done;
-
- if (fseek(f, 0, SEEK_SET) == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
-
- while ((linelen = getline(&line, &linesize, f)) != -1) {
- error = gw_colordiff_line(gw_trans, line);
- if (error)
- goto done;
- /* XXX: KHTML_PRETTY breaks this */
- kerr = khtml_puts(gw_trans->gw_html_req, line);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- }
- if (linelen == -1 && ferror(f))
- error = got_error_from_errno("getline");
-done:
- if (f && fclose(f) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- if (f1 && fclose(f1) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- if (f2 && fclose(f2) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- if (fd1 != -1 && close(fd1) == -1 && error == NULL)
- error = got_error_from_errno("close");
- if (fd2 != -1 && close(fd2) == -1 && error == NULL)
- error = got_error_from_errno("close");
- free(line);
- free(label1);
- free(label2);
- free(id1);
- free(id2);
-
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_get_repo_owner(char **owner, struct gw_trans *gw_trans, char *dir)
-{
- const struct got_error *error = NULL, *close_err;
- struct got_repository *repo;
- const char *gitconfig_owner;
-
- *owner = NULL;
-
- if (gw_trans->gw_conf->got_show_repo_owner == 0)
- return NULL;
-
- error = got_repo_open(&repo, dir, NULL, gw_trans->pack_fds);
- if (error)
- return error;
-
- gitconfig_owner = got_repo_get_gitconfig_owner(repo);
- if (gitconfig_owner) {
- *owner = strdup(gitconfig_owner);
- if (*owner == NULL)
- error = got_error_from_errno("strdup");
- }
- close_err = got_repo_close(repo);
- if (error == NULL)
- error = close_err;
- return error;
-}
-
-static const struct got_error *
-gw_get_clone_url(char **url, struct gw_trans *gw_trans, char *dir)
-{
- const struct got_error *error = NULL;
- FILE *f;
- char *d_file = NULL;
- unsigned int len;
- size_t n;
-
- *url = NULL;
-
- if (asprintf(&d_file, "%s/cloneurl", dir) == -1)
- return got_error_from_errno("asprintf");
-
- f = fopen(d_file, "re");
- if (f == NULL) {
- if (errno != ENOENT && errno != EACCES)
- error = got_error_from_errno2("fopen", d_file);
- goto done;
- }
-
- if (fseek(f, 0, SEEK_END) == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
- len = ftell(f);
- if (len == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
- if (fseek(f, 0, SEEK_SET) == -1) {
- error = got_ferror(f, GOT_ERR_IO);
- goto done;
- }
-
- *url = calloc(len + 1, sizeof(**url));
- if (*url == NULL) {
- error = got_error_from_errno("calloc");
- goto done;
- }
-
- n = fread(*url, 1, len, f);
- if (n == 0 && ferror(f))
- error = got_ferror(f, GOT_ERR_IO);
-done:
- if (f && fclose(f) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- free(d_file);
- return NULL;
-}
-
-static const struct got_error *
-gw_output_repo_tags(struct gw_trans *gw_trans, struct gw_header *header,
- int limit, int tag_type)
-{
- const struct got_error *error = NULL;
- struct got_reflist_head refs;
- struct got_reflist_entry *re;
- char *age = NULL;
- char *id_str = NULL, *newline, *href_commits = NULL;
- char *tag_commit0 = NULL, *href_tag = NULL, *href_briefs = NULL;
- struct got_tag_object *tag = NULL;
- enum kcgi_err kerr = KCGI_OK;
- int summary_header_displayed = 0, chk_next = 0;
- int tag_count = 0, commit_found = 0, c_cnt = 0;
-
- TAILQ_INIT(&refs);
-
- error = got_ref_list(&refs, gw_trans->repo, "refs/tags",
- got_ref_cmp_tags, gw_trans->repo);
- if (error)
- goto done;
-
- TAILQ_FOREACH(re, &refs, entry) {
- const char *refname;
- const char *tagger;
- const char *tag_commit;
- time_t tagger_time;
- struct got_object_id *id;
- struct got_commit_object *commit = NULL;
-
- refname = got_ref_get_name(re->ref);
- if (strncmp(refname, "refs/tags/", 10) != 0)
- continue;
- refname += 10;
-
- error = got_ref_resolve(&id, gw_trans->repo, re->ref);
- if (error)
- goto done;
-
- error = got_object_open_as_tag(&tag, gw_trans->repo, id);
- if (error) {
- if (error->code != GOT_ERR_OBJ_TYPE) {
- free(id);
- goto done;
- }
- /* "lightweight" tag */
- error = got_object_open_as_commit(&commit,
- gw_trans->repo, id);
- if (error) {
- free(id);
- goto done;
- }
- tagger = got_object_commit_get_committer(commit);
- tagger_time =
- got_object_commit_get_committer_time(commit);
- error = got_object_id_str(&id_str, id);
- free(id);
- } else {
- free(id);
- tagger = got_object_tag_get_tagger(tag);
- tagger_time = got_object_tag_get_tagger_time(tag);
- error = got_object_id_str(&id_str,
- got_object_tag_get_object_id(tag));
- }
- if (error)
- goto done;
-
- if (tag_type == TAGFULL && strncmp(id_str, header->commit_id,
- strlen(id_str)) != 0)
- continue;
-
- if (tag_type == TAGBRIEF && gw_trans->commit_id &&
- commit_found == 0 && strncmp(id_str, gw_trans->commit_id,
- strlen(id_str)) != 0)
- continue;
- else
- commit_found = 1;
-
- tag_count++;
-
- if (chk_next) {
- gw_trans->next_id = strdup(id_str);
- if (gw_trans->next_id == NULL)
- error = got_error_from_errno("strdup");
- goto prev;
- }
-
- if (commit) {
- error = got_object_commit_get_logmsg(&tag_commit0,
- commit);
- if (error)
- goto done;
- got_object_commit_close(commit);
- } else {
- tag_commit0 = strdup(got_object_tag_get_message(tag));
- if (tag_commit0 == NULL) {
- error = got_error_from_errno("strdup");
- goto done;
- }
- }
-
- tag_commit = tag_commit0;
- while (*tag_commit == '\n')
- tag_commit++;
-
- switch (tag_type) {
- case TAGBRIEF:
- newline = strchr(tag_commit, '\n');
- if (newline)
- *newline = '\0';
-
- if (summary_header_displayed == 0) {
- kerr = khtml_attr(gw_trans->gw_html_req,
- KELEM_DIV, KATTR_ID,
- "summary_tags_title_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req,
- KELEM_DIV, KATTR_ID,
- "summary_tags_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- "Tags");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req,
- 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req,
- KELEM_DIV, KATTR_ID,
- "summary_tags_content", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- summary_header_displayed = 1;
- }
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_get_time_str(&age, tagger_time, TM_DIFF);
- if (error)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- age ? age : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, refname);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_name", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- href_tag = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "tag", "commit",
- id_str, NULL);
- if (href_tag == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_tag, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, tag_commit);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "navs", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_tag, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "tag");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_briefs = khttp_urlpart(NULL, NULL, "gotweb",
- "path", gw_trans->repo_name, "action", "briefs",
- "commit", id_str, NULL);
- if (href_briefs == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_briefs, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- "commit briefs");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_commits = khttp_urlpart(NULL, NULL, "gotweb",
- "path", gw_trans->repo_name, "action", "commits",
- "commit", id_str, NULL);
- if (href_commits == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_commits, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "commits");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- break;
- case TAGFULL:
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_info_date_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Tag Date:");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_info_date", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- error = gw_get_time_str(&age, tagger_time, TM_LONG);
- if (error)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- age ? age : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_info_tagger_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Tagger:");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_info_date", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, tagger);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tag_info", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khttp_puts(gw_trans->gw_req, tag_commit);
- if (kerr != KCGI_OK)
- goto done;
- break;
- default:
- break;
- }
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- if (limit && --limit == 0)
- chk_next = 1;
-
- if (tag)
- got_object_tag_close(tag);
- tag = NULL;
- free(id_str);
- id_str = NULL;
- free(age);
- age = NULL;
- free(tag_commit0);
- tag_commit0 = NULL;
- free(href_tag);
- href_tag = NULL;
- free(href_briefs);
- href_briefs = NULL;
- free(href_commits);
- href_commits = NULL;
- }
- if (tag_count == 0) {
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "summary_tags_title_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "summary_tags_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Tags");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "summary_tags_content", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "tags_info", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khttp_puts(gw_trans->gw_req,
- "There are no tags for this repo.");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- goto done;
- }
-prev:
- commit_found = 0;
- TAILQ_FOREACH_REVERSE(re, &refs, got_reflist_head, entry) {
- const char *refname;
- struct got_object_id *id;
- struct got_commit_object *commit = NULL;
-
- refname = got_ref_get_name(re->ref);
- if (strncmp(refname, "refs/tags/", 10) != 0)
- continue;
- refname += 10;
-
- error = got_ref_resolve(&id, gw_trans->repo, re->ref);
- if (error)
- goto done;
-
- error = got_object_open_as_tag(&tag, gw_trans->repo, id);
- if (error) {
- if (error->code != GOT_ERR_OBJ_TYPE) {
- free(id);
- goto done;
- }
- /* "lightweight" tag */
- error = got_object_open_as_commit(&commit,
- gw_trans->repo, id);
- if (error) {
- free(id);
- goto done;
- }
- error = got_object_id_str(&id_str, id);
- free(id);
- } else {
- free(id);
- error = got_object_id_str(&id_str,
- got_object_tag_get_object_id(tag));
- }
- if (error)
- goto done;
-
- if (tag_type == TAGFULL && strncmp(id_str, header->commit_id,
- strlen(id_str)) != 0)
- continue;
-
- if (commit_found == 0 && tag_type == TAGBRIEF &&
- gw_trans->commit_id != NULL &&
- strncmp(id_str, gw_trans->commit_id, strlen(id_str)) != 0)
- continue;
- else
- commit_found = 1;
-
- if (gw_trans->commit_id != NULL &&
- strcmp(id_str, gw_trans->commit_id) != 0 &&
- (re == TAILQ_FIRST(&refs) ||
- c_cnt == gw_trans->gw_conf->got_max_commits_display)) {
- gw_trans->prev_id = strdup(id_str);
- if (gw_trans->prev_id == NULL) {
- error = got_error_from_errno("strdup");
- goto done;
- }
- break;
- }
- c_cnt++;
- }
-done:
- if (tag)
- got_object_tag_close(tag);
- free(id_str);
- free(age);
- free(tag_commit0);
- free(href_tag);
- free(href_briefs);
- free(href_commits);
- got_ref_list_free(&refs);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static void
-gw_free_header(struct gw_header *header)
-{
- free(header->path);
- free(header->author);
- free(header->committer);
- free(header->refs_str);
- free(header->commit_id);
- free(header->parent_id);
- free(header->tree_id);
- free(header->commit_msg);
-}
-
-static struct gw_header *
-gw_init_header()
-{
- struct gw_header *header;
-
- header = malloc(sizeof(*header));
- if (header == NULL)
- return NULL;
-
- header->path = NULL;
- TAILQ_INIT(&header->refs);
-
- header->refs_str = NULL;
- header->commit_id = NULL;
- header->committer = NULL;
- header->author = NULL;
- header->parent_id = NULL;
- header->tree_id = NULL;
- header->commit_msg = NULL;
-
- return header;
-}
-
-static const struct got_error *
-gw_get_commits(struct gw_trans * gw_trans, struct gw_header *header,
- int limit, struct got_object_id *iter_start_id)
-{
- const struct got_error *error = NULL;
- struct got_commit_graph *graph = NULL;
- struct got_commit_object *commit = NULL;
- int chk_next = 0, chk_multi = 0, c_cnt = 0, commit_found = 0;
- struct gw_header *t_header = NULL;
-
- error = got_commit_graph_open(&graph, header->path, 0);
- if (error)
- return error;
-
- error = got_commit_graph_iter_start(graph, iter_start_id,
- gw_trans->repo, NULL, NULL);
- if (error)
- goto err;
-
- for (;;) {
- struct got_object_id id;
-
- error = got_commit_graph_iter_next(&id, graph, gw_trans->repo,
- NULL, NULL);
- if (error) {
- if (error->code == GOT_ERR_ITER_COMPLETED)
- error = NULL;
- goto done;
- }
-
- error = got_object_open_as_commit(&commit, gw_trans->repo, &id);
- if (error)
- goto err;
- if (limit == 1 && chk_multi == 0 &&
- gw_trans->gw_conf->got_max_commits_display != 1) {
- error = gw_get_commit(gw_trans, header, commit, &id);
- if (error)
- goto err;
- commit_found = 1;
- } else {
- chk_multi = 1;
- struct gw_header *n_header = NULL;
- if ((n_header = gw_init_header()) == NULL) {
- error = got_error_from_errno("malloc");
- goto err;
- }
- TAILQ_INSERT_TAIL(&gw_trans->gw_headers, n_header,
- entry);
- error = got_ref_list(&n_header->refs, gw_trans->repo,
- NULL, got_ref_cmp_by_name, NULL);
- if (error)
- goto err;
-
- error = gw_get_commit(gw_trans, n_header, commit, &id);
- if (error)
- goto err;
- got_ref_list_free(&n_header->refs);
-
- if (gw_trans->commit_id != NULL) {
- if (strcmp(gw_trans->commit_id,
- n_header->commit_id) == 0)
- commit_found = 1;
- } else
- commit_found = 1;
-
- /*
- * check for one more commit before breaking,
- * so we know whether to navigate through gw_briefs
- * gw_commits and gw_summary
- */
- if (chk_next && (gw_trans->action == GW_BRIEFS ||
- gw_trans->action == GW_COMMITS ||
- gw_trans->action == GW_SUMMARY)) {
- gw_trans->next_id = strdup(n_header->commit_id);
- if (gw_trans->next_id == NULL)
- error = got_error_from_errno("strdup");
- TAILQ_REMOVE(&gw_trans->gw_headers, n_header,
- entry);
- goto done;
- }
-
- }
- if (commit_found == 1 && (error || (limit && --limit == 0))) {
- if (chk_multi == 0)
- break;
- chk_next = 1;
- }
- }
-done:
- if (gw_trans->prev_id == NULL && gw_trans->commit_id != NULL &&
- (gw_trans->action == GW_BRIEFS || gw_trans->action == GW_COMMITS)) {
- commit_found = 0;
- TAILQ_FOREACH_REVERSE(t_header, &gw_trans->gw_headers,
- headers, entry) {
- if (commit_found == 0 &&
- strcmp(gw_trans->commit_id,
- t_header->commit_id) != 0)
- continue;
- else
- commit_found = 1;
- if (gw_trans->commit_id != NULL &&
- strcmp(gw_trans->commit_id,
- t_header->commit_id) != 0 &&
- (c_cnt == gw_trans->gw_conf->got_max_commits_display
- || t_header ==
- TAILQ_FIRST(&gw_trans->gw_headers))) {
- gw_trans->prev_id = strdup(t_header->commit_id);
- if (gw_trans->prev_id == NULL)
- error = got_error_from_errno("strdup");
- break;
- }
- c_cnt++;
- }
- }
-err:
- if (commit != NULL)
- got_object_commit_close(commit);
- if (graph)
- got_commit_graph_close(graph);
- return error;
-}
-
-static const struct got_error *
-gw_get_commit(struct gw_trans *gw_trans, struct gw_header *header,
- struct got_commit_object *commit, struct got_object_id *id)
-{
- const struct got_error *error = NULL;
- struct got_reflist_entry *re;
- struct got_object_id *id2 = NULL;
- struct got_object_qid *parent_id;
- char *commit_msg = NULL, *commit_msg0;
-
- /*print commit*/
- TAILQ_FOREACH(re, &header->refs, entry) {
- char *s;
- const char *name;
- struct got_tag_object *tag = NULL;
- struct got_object_id *ref_id;
- int cmp;
-
- if (got_ref_is_symbolic(re->ref))
- continue;
-
- name = got_ref_get_name(re->ref);
- if (strncmp(name, "refs/", 5) == 0)
- name += 5;
- if (strncmp(name, "got/", 4) == 0)
- continue;
- if (strncmp(name, "heads/", 6) == 0)
- name += 6;
- if (strncmp(name, "remotes/", 8) == 0) {
- name += 8;
- s = strstr(name, "/" GOT_REF_HEAD);
- if (s != NULL && s[strlen(s)] == '\0')
- continue;
- }
- error = got_ref_resolve(&ref_id, gw_trans->repo, re->ref);
- if (error)
- return error;
- if (strncmp(name, "tags/", 5) == 0) {
- error = got_object_open_as_tag(&tag, gw_trans->repo,
- ref_id);
- if (error) {
- if (error->code != GOT_ERR_OBJ_TYPE) {
- free(ref_id);
- continue;
- }
- /*
- * Ref points at something other
- * than a tag.
- */
- error = NULL;
- tag = NULL;
- }
- }
- cmp = got_object_id_cmp(tag ?
- got_object_tag_get_object_id(tag) : ref_id, id);
- free(ref_id);
- if (tag)
- got_object_tag_close(tag);
- if (cmp != 0)
- continue;
- s = header->refs_str;
- if (asprintf(&header->refs_str, "%s%s%s", s ? s : "",
- s ? ", " : "", name) == -1) {
- error = got_error_from_errno("asprintf");
- free(s);
- header->refs_str = NULL;
- return error;
- }
- free(s);
- }
-
- error = got_object_id_str(&header->commit_id, id);
- if (error)
- return error;
-
- error = got_object_id_str(&header->tree_id,
- got_object_commit_get_tree_id(commit));
- if (error)
- return error;
-
- if (gw_trans->action == GW_DIFF) {
- parent_id = STAILQ_FIRST(
- got_object_commit_get_parent_ids(commit));
- if (parent_id != NULL) {
- id2 = got_object_id_dup(&parent_id->id);
- free (parent_id);
- error = got_object_id_str(&header->parent_id, id2);
- if (error)
- return error;
- free(id2);
- } else {
- header->parent_id = strdup("/dev/null");
- if (header->parent_id == NULL) {
- error = got_error_from_errno("strdup");
- return error;
- }
- }
- }
-
- header->committer_time =
- got_object_commit_get_committer_time(commit);
-
- header->author =
- strdup(got_object_commit_get_author(commit));
- if (header->author == NULL) {
- error = got_error_from_errno("strdup");
- return error;
- }
- header->committer =
- strdup(got_object_commit_get_committer(commit));
- if (header->committer == NULL) {
- error = got_error_from_errno("strdup");
- return error;
- }
- error = got_object_commit_get_logmsg(&commit_msg0, commit);
- if (error)
- return error;
-
- commit_msg = commit_msg0;
- while (*commit_msg == '\n')
- commit_msg++;
-
- header->commit_msg = strdup(commit_msg);
- if (header->commit_msg == NULL)
- error = got_error_from_errno("strdup");
- free(commit_msg0);
- return error;
-}
-
-static const struct got_error *
-gw_get_header(struct gw_trans *gw_trans, struct gw_header *header, int limit)
-{
- const struct got_error *error = NULL;
- char *in_repo_path = NULL;
- struct got_object_id *id = NULL;
- struct got_reference *ref;
-
- error = got_repo_open(&gw_trans->repo, gw_trans->repo_path, NULL,
- gw_trans->pack_fds);
- if (error)
- return error;
-
- if (gw_trans->commit_id == NULL || gw_trans->action == GW_COMMITS ||
- gw_trans->action == GW_BRIEFS || gw_trans->action == GW_SUMMARY ||
- gw_trans->action == GW_TAGS) {
- error = got_ref_open(&ref, gw_trans->repo,
- gw_trans->headref, 0);
- if (error)
- return error;
-
- error = got_ref_resolve(&id, gw_trans->repo, ref);
- got_ref_close(ref);
- if (error)
- return error;
- } else {
- error = got_ref_open(&ref, gw_trans->repo,
- gw_trans->commit_id, 0);
- if (error == NULL) {
- int obj_type;
- error = got_ref_resolve(&id, gw_trans->repo, ref);
- got_ref_close(ref);
- if (error)
- return error;
- error = got_object_get_type(&obj_type, gw_trans->repo,
- id);
- if (error)
- goto done;
- if (obj_type == GOT_OBJ_TYPE_TAG) {
- struct got_tag_object *tag;
- error = got_object_open_as_tag(&tag,
- gw_trans->repo, id);
- if (error)
- goto done;
- if (got_object_tag_get_object_type(tag) !=
- GOT_OBJ_TYPE_COMMIT) {
- got_object_tag_close(tag);
- error = got_error(GOT_ERR_OBJ_TYPE);
- goto done;
- }
- free(id);
- id = got_object_id_dup(
- got_object_tag_get_object_id(tag));
- if (id == NULL)
- error = got_error_from_errno(
- "got_object_id_dup");
- got_object_tag_close(tag);
- if (error)
- goto done;
- } else if (obj_type != GOT_OBJ_TYPE_COMMIT) {
- error = got_error(GOT_ERR_OBJ_TYPE);
- goto done;
- }
- }
- error = got_repo_match_object_id_prefix(&id,
- gw_trans->commit_id, GOT_OBJ_TYPE_COMMIT,
- gw_trans->repo);
- if (error)
- goto done;
- }
-
- error = got_repo_map_path(&in_repo_path, gw_trans->repo,
- gw_trans->repo_path);
- if (error)
- goto done;
-
- if (in_repo_path) {
- header->path = strdup(in_repo_path);
- if (header->path == NULL) {
- error = got_error_from_errno("strdup");
- goto done;
- }
- }
-
- error = got_ref_list(&header->refs, gw_trans->repo, NULL,
- got_ref_cmp_by_name, NULL);
- if (error)
- goto done;
-
- error = gw_get_commits(gw_trans, header, limit, id);
-done:
- free(id);
- free(in_repo_path);
- return error;
-}
-
-struct blame_line {
- int annotated;
- char *id_str;
- char *committer;
- char datebuf[11]; /* YYYY-MM-DD + NUL */
-};
-
-struct gw_blame_cb_args {
- struct blame_line *lines;
- int nlines;
- int nlines_prec;
- int lineno_cur;
- off_t *line_offsets;
- FILE *f;
- struct got_repository *repo;
- struct gw_trans *gw_trans;
-};
-
-static const struct got_error *
-gw_blame_cb(void *arg, int nlines, int lineno,
- struct got_commit_object *commit, struct got_object_id *id)
-{
- const struct got_error *err = NULL;
- struct gw_blame_cb_args *a = arg;
- struct blame_line *bline;
- char *line = NULL;
- size_t linesize = 0;
- off_t offset;
- struct tm tm;
- time_t committer_time;
- enum kcgi_err kerr = KCGI_OK;
-
- if (nlines != a->nlines ||
- (lineno != -1 && lineno < 1) || lineno > a->nlines)
- return got_error(GOT_ERR_RANGE);
-
- if (lineno == -1)
- return NULL; /* no change in this commit */
-
- /* Annotate this line. */
- bline = &a->lines[lineno - 1];
- if (bline->annotated)
- return NULL;
- err = got_object_id_str(&bline->id_str, id);
- if (err)
- return err;
-
- bline->committer = strdup(got_object_commit_get_committer(commit));
- if (bline->committer == NULL) {
- err = got_error_from_errno("strdup");
- goto done;
- }
-
- committer_time = got_object_commit_get_committer_time(commit);
- if (gmtime_r(&committer_time, &tm) == NULL)
- return got_error_from_errno("gmtime_r");
- if (strftime(bline->datebuf, sizeof(bline->datebuf), "%G-%m-%d",
- &tm) == 0) {
- err = got_error(GOT_ERR_NO_SPACE);
- goto done;
- }
- bline->annotated = 1;
-
- /* Print lines annotated so far. */
- bline = &a->lines[a->lineno_cur - 1];
- if (!bline->annotated)
- goto done;
-
- offset = a->line_offsets[a->lineno_cur - 1];
- if (fseeko(a->f, offset, SEEK_SET) == -1) {
- err = got_error_from_errno("fseeko");
- goto done;
- }
-
- while (a->lineno_cur <= a->nlines && bline->annotated) {
- char *smallerthan, *at, *nl, *committer;
- char *href_diff = NULL;
- size_t len;
-
- if (getline(&line, &linesize, a->f) == -1) {
- if (ferror(a->f))
- err = got_error_from_errno("getline");
- break;
- }
-
- committer = bline->committer;
- smallerthan = strchr(committer, '<');
- if (smallerthan && smallerthan[1] != '\0')
- committer = smallerthan + 1;
- at = strchr(committer, '@');
- if (at)
- *at = '\0';
- len = strlen(committer);
- if (len >= 9)
- committer[8] = '\0';
-
- nl = strchr(line, '\n');
- if (nl)
- *nl = '\0';
-
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_number", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_printf(a->gw_trans->gw_html_req, "%.*d",
- a->nlines_prec, a->lineno_cur);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto err;
-
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_hash", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
-
- href_diff = khttp_urlpart(NULL, NULL, "gotweb", "path",
- a->gw_trans->repo_name, "action", "diff", "commit",
- bline->id_str, NULL);
- if (href_diff == NULL) {
- err = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_diff, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(a->gw_trans->gw_html_req, "%.8s",
- bline->id_str);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto err;
-
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_date", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_puts(a->gw_trans->gw_html_req, bline->datebuf);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto err;
-
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_author", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_puts(a->gw_trans->gw_html_req, committer);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto err;
-
- kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "blame_code", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_puts(a->gw_trans->gw_html_req, line);
- if (kerr != KCGI_OK)
- goto err;
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto err;
-
- kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto err;
-
- a->lineno_cur++;
- bline = &a->lines[a->lineno_cur - 1];
-err:
- free(href_diff);
- }
-done:
- free(line);
- if (err == NULL && kerr != KCGI_OK)
- err = gw_kcgi_error(kerr);
- return err;
-}
-
-static const struct got_error *
-gw_output_file_blame(struct gw_trans *gw_trans, struct gw_header *header)
-{
- const struct got_error *error = NULL;
- struct got_object_id *obj_id = NULL;
- struct got_object_id *commit_id = NULL;
- struct got_commit_object *commit = NULL;
- struct got_blob_object *blob = NULL;
- char *path = NULL, *in_repo_path = NULL;
- struct gw_blame_cb_args bca;
- int i, obj_type, fd1 = -1, fd2 = -1, fd3 = -1;
- off_t filesize;
- FILE *f1 = NULL, *f2 = NULL;
-
- fd1 = got_opentempfd();
- if (fd1 == -1)
- return got_error_from_errno("got_opentempfd");
- fd2 = got_opentempfd();
- if (fd2 == -1) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
- fd3 = got_opentempfd();
- if (fd3 == -1) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
-
- memset(&bca, 0, sizeof(bca));
-
- if (asprintf(&path, "%s%s%s",
- gw_trans->repo_folder ? gw_trans->repo_folder : "",
- gw_trans->repo_folder ? "/" : "",
- gw_trans->repo_file) == -1) {
- error = got_error_from_errno("asprintf");
- goto done;
- }
-
- error = got_repo_map_path(&in_repo_path, gw_trans->repo, path);
- if (error)
- goto done;
-
- error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit_id,
- GOT_OBJ_TYPE_COMMIT, &header->refs, gw_trans->repo);
- if (error)
- goto done;
-
- error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id);
- if (error)
- goto done;
-
- error = got_object_id_by_path(&obj_id, gw_trans->repo, commit,
- in_repo_path);
- if (error)
- goto done;
-
- if (obj_id == NULL) {
- error = got_error(GOT_ERR_NO_OBJ);
- goto done;
- }
-
- error = got_object_get_type(&obj_type, gw_trans->repo, obj_id);
- if (error)
- goto done;
-
- if (obj_type != GOT_OBJ_TYPE_BLOB) {
- error = got_error(GOT_ERR_OBJ_TYPE);
- goto done;
- }
-
- error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192,
- fd1);
- if (error)
- goto done;
-
- bca.f = got_opentemp();
- if (bca.f == NULL) {
- error = got_error_from_errno("got_opentemp");
- goto done;
- }
- error = got_object_blob_dump_to_file(&filesize, &bca.nlines,
- &bca.line_offsets, bca.f, blob);
- if (error || bca.nlines == 0)
- goto done;
-
- /* Don't include \n at EOF in the blame line count. */
- if (bca.line_offsets[bca.nlines - 1] == filesize)
- bca.nlines--;
-
- bca.lines = calloc(bca.nlines, sizeof(*bca.lines));
- if (bca.lines == NULL) {
- error = got_error_from_errno("calloc");
- goto done;
- }
- bca.lineno_cur = 1;
- bca.nlines_prec = 0;
- i = bca.nlines;
- while (i > 0) {
- i /= 10;
- bca.nlines_prec++;
- }
- bca.repo = gw_trans->repo;
- bca.gw_trans = gw_trans;
-
- fd1 = got_opentempfd();
- if (fd1 == -1) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
-
- f1 = got_opentemp();
- if (f1 == NULL) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
- f2 = got_opentemp();
- if (f2 == NULL) {
- error = got_error_from_errno("got_opentempfd");
- goto done;
- }
-
- error = got_blame(in_repo_path, commit_id, gw_trans->repo,
- GOT_DIFF_ALGORITHM_PATIENCE, gw_blame_cb, &bca, NULL, NULL,
- fd2, fd3, f1, f2);
-done:
- free(in_repo_path);
- free(commit_id);
- free(obj_id);
- free(path);
-
- if (fd1 != -1 && close(fd1) == -1 && error == NULL)
- error = got_error_from_errno("close");
- if (fd2 != -1 && close(fd2) == -1 && error == NULL)
- error = got_error_from_errno("close");
- if (fd3 != -1 && close(fd3) == -1 && error == NULL)
- error = got_error_from_errno("close");
- if (f1 && fclose(f1) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- if (f2 && fclose(f2) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
-
- if (blob) {
- free(bca.line_offsets);
- for (i = 0; i < bca.nlines; i++) {
- struct blame_line *bline = &bca.lines[i];
- free(bline->id_str);
- free(bline->committer);
- }
- free(bca.lines);
- if (bca.f && fclose(bca.f) == EOF && error == NULL)
- error = got_error_from_errno("fclose");
- }
- if (blob)
- got_object_blob_close(blob);
- if (commit)
- got_object_commit_close(commit);
- return error;
-}
-
-static const struct got_error *
-gw_output_blob_buf(struct gw_trans *gw_trans, struct gw_header *header)
-{
- const struct got_error *error = NULL;
- struct got_object_id *obj_id = NULL;
- struct got_object_id *commit_id = NULL;
- struct got_commit_object *commit = NULL;
- struct got_blob_object *blob = NULL;
- char *path = NULL, *in_repo_path = NULL;
- int obj_type, set_mime = 0, fd = -1;
- size_t len, hdrlen;
- const uint8_t *buf;
- enum kcgi_err kerr = KCGI_OK;
-
- fd = got_opentempfd();
- if (fd == -1)
- return got_error_from_errno("got_opentempfd");
-
- if (asprintf(&path, "%s%s%s",
- gw_trans->repo_folder ? gw_trans->repo_folder : "",
- gw_trans->repo_folder ? "/" : "",
- gw_trans->repo_file) == -1) {
- error = got_error_from_errno("asprintf");
- goto done;
- }
-
- error = got_repo_map_path(&in_repo_path, gw_trans->repo, path);
- if (error)
- goto done;
-
- error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit_id,
- GOT_OBJ_TYPE_COMMIT, &header->refs, gw_trans->repo);
- if (error)
- goto done;
-
- error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id);
- if (error)
- goto done;
-
- error = got_object_id_by_path(&obj_id, gw_trans->repo, commit,
- in_repo_path);
- if (error)
- goto done;
-
- if (obj_id == NULL) {
- error = got_error(GOT_ERR_NO_OBJ);
- goto done;
- }
-
- error = got_object_get_type(&obj_type, gw_trans->repo, obj_id);
- if (error)
- goto done;
-
- if (obj_type != GOT_OBJ_TYPE_BLOB) {
- error = got_error(GOT_ERR_OBJ_TYPE);
- goto done;
- }
-
- error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192,
- fd);
- if (error)
- goto done;
-
- hdrlen = got_object_blob_get_hdrlen(blob);
- do {
- error = got_object_blob_read_block(&len, blob);
- if (error)
- goto done;
- buf = got_object_blob_get_read_buf(blob);
-
- /*
- * Skip blob object header first time around,
- * which also contains a zero byte.
- */
- buf += hdrlen;
- if (set_mime == 0) {
- if (isbinary(buf, len - hdrlen))
- gw_trans->mime = KMIME_APP_OCTET_STREAM;
- else
- gw_trans->mime = KMIME_TEXT_PLAIN;
- set_mime = 1;
- error = gw_display_index(gw_trans);
- if (error)
- goto done;
- }
- kerr = khttp_write(gw_trans->gw_req, buf, len - hdrlen);
- if (kerr != KCGI_OK)
- goto done;
- hdrlen = 0;
- } while (len != 0);
-done:
- free(in_repo_path);
- free(commit_id);
- free(obj_id);
- free(path);
- if (fd != -1 && close(fd) == -1 && error == NULL)
- error = got_error_from_errno("close");
- if (blob)
- got_object_blob_close(blob);
- if (commit)
- got_object_commit_close(commit);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_output_repo_tree(struct gw_trans *gw_trans, struct gw_header *header)
-{
- const struct got_error *error = NULL;
- struct got_object_id *tree_id = NULL, *commit_id = NULL;
- struct got_tree_object *tree = NULL;
- struct got_commit_object *commit = NULL;
- char *path = NULL, *in_repo_path = NULL;
- char *id_str = NULL;
- char *build_folder = NULL;
- char *href_blob = NULL, *href_blame = NULL;
- const char *class = NULL;
- int nentries, i, class_flip = 0;
- enum kcgi_err kerr = KCGI_OK;
-
- if (gw_trans->repo_folder != NULL) {
- path = strdup(gw_trans->repo_folder);
- if (path == NULL) {
- error = got_error_from_errno("strdup");
- goto done;
- }
- } else {
- error = got_repo_map_path(&in_repo_path, gw_trans->repo,
- gw_trans->repo_path);
- if (error)
- goto done;
- free(path);
- path = in_repo_path;
- }
-
- if (gw_trans->commit_id == NULL) {
- struct got_reference *head_ref;
- error = got_ref_open(&head_ref, gw_trans->repo,
- gw_trans->headref, 0);
- if (error)
- goto done;
- error = got_ref_resolve(&commit_id, gw_trans->repo, head_ref);
- if (error)
- goto done;
- got_ref_close(head_ref);
- /*
- * gw_trans->commit_id was not parsed from the querystring
- * we hit this code path from gw_index, where we don't know the
- * commit values for the tree link yet, so set
- * gw_trans->commit_id here to continue further into the tree
- */
- error = got_object_id_str(&gw_trans->commit_id, commit_id);
- if (error)
- goto done;
-
- } else {
- error = got_repo_match_object_id(&commit_id, NULL,
- gw_trans->commit_id, GOT_OBJ_TYPE_COMMIT, &header->refs,
- gw_trans->repo);
- if (error)
- goto done;
- }
-
- error = got_object_open_as_commit(&commit, gw_trans->repo, commit_id);
- if (error)
- goto done;
-
- error = got_object_id_by_path(&tree_id, gw_trans->repo, commit,
- path);
- if (error)
- goto done;
-
- error = got_object_open_as_tree(&tree, gw_trans->repo, tree_id);
- if (error)
- goto done;
-
- nentries = got_object_tree_get_nentries(tree);
- for (i = 0; i < nentries; i++) {
- struct got_tree_entry *te;
- const char *modestr = "";
- mode_t mode;
-
- te = got_object_tree_get_entry(tree, i);
-
- error = got_object_id_str(&id_str, got_tree_entry_get_id(te));
- if (error)
- goto done;
-
- mode = got_tree_entry_get_mode(te);
- if (got_object_tree_entry_is_submodule(te))
- modestr = "$";
- else if (S_ISLNK(mode))
- modestr = "@";
- else if (S_ISDIR(mode))
- modestr = "/";
- else if (mode & S_IXUSR)
- modestr = "*";
-
- if (class_flip == 0) {
- class = "back_lightgray";
- class_flip = 1;
- } else {
- class = "back_white";
- class_flip = 0;
- }
-
- if (S_ISDIR(mode)) {
- if (asprintf(&build_folder, "%s/%s",
- gw_trans->repo_folder ? gw_trans->repo_folder : "",
- got_tree_entry_get_name(te)) == -1) {
- error = got_error_from_errno("asprintf");
- goto done;
- }
-
- href_blob = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action",
- gw_get_action_name(gw_trans), "commit",
- gw_trans->commit_id, "folder", build_folder, NULL);
- if (href_blob == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_line", KATTR_CLASS, class,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_blob, KATTR_CLASS,
- "diff_directory", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, "%s%s",
- got_tree_entry_get_name(te), modestr);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_line_blank", KATTR_CLASS, class,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_entity(gw_trans->gw_html_req,
- KENTITY_nbsp);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- } else {
- href_blob = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "blob", "commit",
- gw_trans->commit_id, "file",
- got_tree_entry_get_name(te), "folder",
- gw_trans->repo_folder ? gw_trans->repo_folder : "",
- NULL);
- if (href_blob == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- href_blame = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "blame", "commit",
- gw_trans->commit_id, "file",
- got_tree_entry_get_name(te), "folder",
- gw_trans->repo_folder ? gw_trans->repo_folder : "",
- NULL);
- if (href_blame == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_line", KATTR_CLASS, class,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_blob, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, "%s%s",
- got_tree_entry_get_name(te), modestr);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "tree_line_navs", KATTR_CLASS, class,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_blob, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "blob");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
- KATTR_HREF, href_blame, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "blame");
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
- }
- free(id_str);
- id_str = NULL;
- free(href_blob);
- href_blob = NULL;
- free(build_folder);
- build_folder = NULL;
- }
-done:
- if (tree)
- got_object_tree_close(tree);
- if (commit)
- got_object_commit_close(commit);
- free(id_str);
- free(href_blob);
- free(href_blame);
- free(in_repo_path);
- free(tree_id);
- free(build_folder);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_output_repo_heads(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- struct got_reflist_head refs;
- struct got_reflist_entry *re;
- char *age = NULL, *href_summary = NULL, *href_briefs = NULL;
- char *href_commits = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- TAILQ_INIT(&refs);
-
- error = got_ref_list(&refs, gw_trans->repo, "refs/heads",
- got_ref_cmp_by_name, NULL);
- if (error)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "summary_heads_title_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "summary_heads_title", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "Heads");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "summary_heads_content", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- TAILQ_FOREACH(re, &refs, entry) {
- const char *refname;
-
- if (got_ref_is_symbolic(re->ref))
- continue;
-
- refname = got_ref_get_name(re->ref);
- if (strncmp(refname, "refs/heads/", 11) != 0)
- continue;
-
- error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
- refname, TM_DIFF);
- if (error)
- goto done;
-
- if (strncmp(refname, "refs/heads/", 11) == 0)
- refname += 11;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "heads_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "heads_age", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, age ? age : "");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "heads_space", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_entity(gw_trans->gw_html_req, KENTITY_nbsp);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
- KATTR_ID, "head", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- href_summary = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "summary", "headref",
- refname, NULL);
- if (href_summary == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_summary, KATTR__MAX);
- kerr = khtml_puts(gw_trans->gw_html_req, refname);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "navs_wrapper", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "navs", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_summary, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "summary");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_briefs = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "briefs", "headref",
- refname, NULL);
- if (href_briefs == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_briefs, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "commit briefs");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_puts(gw_trans->gw_html_req, " | ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_commits = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "commits", "headref",
- refname, NULL);
- if (href_commits == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_commits, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, "commits");
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
- if (kerr != KCGI_OK)
- goto done;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "dotted_line", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
- if (kerr != KCGI_OK)
- goto done;
- free(href_summary);
- href_summary = NULL;
- free(href_briefs);
- href_briefs = NULL;
- free(href_commits);
- href_commits = NULL;
- }
-done:
- got_ref_list_free(&refs);
- free(href_summary);
- free(href_briefs);
- free(href_commits);
- return error;
-}
-
-static const struct got_error *
-gw_output_site_link(struct gw_trans *gw_trans)
-{
- const struct got_error *error = NULL;
- char *href_summary = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "site_link", KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF, GOTWEB,
- KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req,
- gw_trans->gw_conf->got_site_link);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-
- if (gw_trans->repo_name != NULL) {
- kerr = khtml_puts(gw_trans->gw_html_req, " / ");
- if (kerr != KCGI_OK)
- goto done;
-
- href_summary = khttp_urlpart(NULL, NULL, "gotweb", "path",
- gw_trans->repo_name, "action", "summary", NULL);
- if (href_summary == NULL) {
- error = got_error_from_errno("khttp_urlpart");
- goto done;
- }
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A, KATTR_HREF,
- href_summary, KATTR__MAX);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_puts(gw_trans->gw_html_req, gw_trans->repo_name);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
- kerr = khtml_printf(gw_trans->gw_html_req, " / %s",
- gw_get_action_name(gw_trans));
- if (kerr != KCGI_OK)
- goto done;
- }
-
- kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
- if (kerr != KCGI_OK)
- goto done;
-done:
- free(href_summary);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-static const struct got_error *
-gw_colordiff_line(struct gw_trans *gw_trans, char *buf)
-{
- const struct got_error *error = NULL;
- const char *color = NULL;
- enum kcgi_err kerr = KCGI_OK;
-
- if (strncmp(buf, "-", 1) == 0)
- color = "diff_minus";
- else if (strncmp(buf, "+", 1) == 0)
- color = "diff_plus";
- else if (strncmp(buf, "@@", 2) == 0)
- color = "diff_chunk_header";
- else if (strncmp(buf, "@@", 2) == 0)
- color = "diff_chunk_header";
- else if (strncmp(buf, "commit +", 8) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "commit -", 8) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "blob +", 6) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "blob -", 6) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "file +", 6) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "file -", 6) == 0)
- color = "diff_meta";
- else if (strncmp(buf, "from:", 5) == 0)
- color = "diff_author";
- else if (strncmp(buf, "via:", 4) == 0)
- color = "diff_author";
- else if (strncmp(buf, "date:", 5) == 0)
- color = "diff_date";
- kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
- "diff_line", KATTR_CLASS, color ? color : "", KATTR__MAX);
- if (error == NULL && kerr != KCGI_OK)
- error = gw_kcgi_error(kerr);
- return error;
-}
-
-int
-main(int argc, char *argv[])
-{
- const struct got_error *error = NULL, *error2 = NULL;
- struct gw_trans *gw_trans;
- struct gw_dir *dir = NULL, *tdir;
- const char *page = "index";
- enum kcgi_err kerr = KCGI_OK;
-
- if ((gw_trans = malloc(sizeof(struct gw_trans))) == NULL)
- errx(1, "malloc");
-
- if ((gw_trans->gw_req = malloc(sizeof(struct kreq))) == NULL)
- errx(1, "malloc");
-
- if ((gw_trans->gw_html_req = malloc(sizeof(struct khtmlreq))) == NULL)
- errx(1, "malloc");
-
- if ((gw_trans->gw_tmpl = malloc(sizeof(struct ktemplate))) == NULL)
- errx(1, "malloc");
-
- kerr = khttp_parse(gw_trans->gw_req, gw_keys, KEY__ZMAX, &page, 1, 0);
- if (kerr != KCGI_OK) {
- error = gw_kcgi_error(kerr);
- goto done;
- }
-
- TAILQ_INIT(&gw_trans->gw_dirs);
- TAILQ_INIT(&gw_trans->gw_headers);
-
- gw_trans->action = -1;
- gw_trans->page = 0;
- gw_trans->repos_total = 0;
- gw_trans->repo_path = NULL;
- gw_trans->commit_id = NULL;
- gw_trans->next_id = NULL;
- gw_trans->prev_id = NULL;
- gw_trans->headref = GOT_REF_HEAD;
- gw_trans->mime = KMIME_TEXT_HTML;
- gw_trans->gw_tmpl->key = gw_templs;
- gw_trans->gw_tmpl->keysz = TEMPL__MAX;
- gw_trans->gw_tmpl->arg = gw_trans;
- gw_trans->gw_tmpl->cb = gw_template;
-
- error = got_repo_pack_fds_open(&gw_trans->pack_fds);
- if (error != NULL)
- goto done;
-
- error = parse_gotweb_config(&gw_trans->gw_conf, GOTWEB_CONF);
- if (error)
- goto done;
-
- error = gw_parse_querystring(gw_trans);
- if (error)
- goto done;
-
- if (gw_trans->repo) {
- const struct got_error *close_err;
- close_err = got_repo_close(gw_trans->repo);
- if (error == NULL)
- error = close_err;
- }
- if (gw_trans->action == GW_BLOB)
- error = gw_blob(gw_trans);
- else
- error = gw_display_index(gw_trans);
-done:
- if (error) {
- gw_trans->error = error;
- gw_trans->action = GW_ERR;
- error2 = gw_display_open(gw_trans, KHTTP_200, gw_trans->mime);
- if (error2)
- goto cleanup; /* we can't display an error page */
- kerr = khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0);
- if (kerr != KCGI_OK)
- goto cleanup; /* we can't display an error page */
- kerr = khttp_template(gw_trans->gw_req, gw_trans->gw_tmpl,
- gw_query_funcs[gw_trans->action].template);
- if (kerr != KCGI_OK) {
- khtml_close(gw_trans->gw_html_req);
- goto cleanup; /* we can't display an error page */
- }
- }
-
-cleanup:
- if (gw_trans->pack_fds) {
- const struct got_error *pack_err =
- got_repo_pack_fds_close(gw_trans->pack_fds);
- if (error == NULL)
- error = pack_err;
- gw_trans->pack_fds = NULL;
- }
- free(gw_trans->gw_conf->got_repos_path);
- free(gw_trans->gw_conf->got_www_path);
- free(gw_trans->gw_conf->got_site_name);
- free(gw_trans->gw_conf->got_site_owner);
- free(gw_trans->gw_conf->got_site_link);
- free(gw_trans->gw_conf->got_logo);
- free(gw_trans->gw_conf->got_logo_url);
- free(gw_trans->gw_conf);
- free(gw_trans->commit_id);
- free(gw_trans->next_id);
- free(gw_trans->prev_id);
- free(gw_trans->repo_path);
- TAILQ_FOREACH_SAFE(dir, &gw_trans->gw_dirs, entry, tdir) {
- free(dir->name);
- free(dir->description);
- free(dir->age);
- free(dir->url);
- free(dir->path);
- free(dir);
- }
-
- khttp_free(gw_trans->gw_req);
- return 0;
-}
blob - b9dd2b0786d5a06a4c43e97bf29aeab25650d68d (mode 644)
blob + /dev/null
--- gotweb/gotweb.conf.5
+++ /dev/null
-.\"
-.\" Copyright (c) 2020 Tracey Emery <tracey@traceyemery.net>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate$
-.Dt GOTWEB.CONF 5
-.Os
-.Sh NAME
-.Nm gotweb.conf
-.Nd gotweb configuration file
-.Sh DESCRIPTION
-.Nm
-is the run-time configuration file for
-.Xr gotweb 8 .
-.Pp
-The file format is line-based, with one configuration directive per line.
-Any lines beginning with a
-.Sq #
-are treated as comments and ignored.
-.Pp
-Paths mentioned in
-.Nm
-must be relative to
-.Pa /var/www ,
-the
-.Xr chroot 2
-environment of
-.Xr httpd 8 .
-.Sh GLOBAL CONFIGURATION
-The available configuration directives are as follows:
-.Bl -tag -width Ds
-.It Ic got_max_commits_display Ar number
-Set the maximum amount of commits displayed per page.
-.It Ic got_logo Ar path
-Set the path to an image file containing a logo to be displayed.
-.It Ic got_logo_url Ar url
-Set a hyperlink for the logo.
-.It Ic got_max_repos Ar number
-Set the maximum amount of repositories
-.Xr gotweb 8
-will work with.
-.It Ic got_max_repos_display Ar number
-Set the maximum amount of repositories displayed on the index screen.
-.It Ic got_show_repo_age Ar on | off
-Toggle display of last repository modification date.
-.It Ic got_show_repo_cloneurl Ar on | off
-Toggle display of clone URLs for a repository.
-This requires the creation of a
-.Pa cloneurl
-file inside the repository which contains one URL per line.
-.It Ic got_show_repo_description Ar on | off
-Toggle display of the repository description.
-The
-.Pa description
-file in the repository should be updated with an appropriate description.
-.It Ic got_repos_path Ar path
-Set the path to the directory which contains Git repositories that
-.Xr gotweb 8
-should publish.
-.It Ic got_show_repo_owner Ar on | off
-Set whether to display the repository owner.
-Displaying the owner requires owner information to be added to the
-.Pa config
-file in the repository.
-.Xr gotweb 8
-will parse owner information from either a [gotweb] or a [gitweb] section.
-For example:
-.Bd -literal -offset indent
-[gotweb]
-owner = "Your Name"
-.Ed
-.It Ic got_site_link Ar string
-Set the displayed site link name for the index page.
-.It Ic got_site_name Ar string
-Set the displayed site name title.
-.It Ic got_site_owner Ar string
-Set the displayed site owner.
-.It Ic got_show_site_owner Ar on | off
-Toggle display of the site owner.
-.It Ic got_www_path Ar string
-Set the public gotweb httpd path.
-.El
-.Sh FILES
-.Bl -tag -width Ds -compact
-.It Pa /var/www/etc/gotweb.conf
-Location of the
-.Nm
-configuration file.
-.El
-.Sh EXAMPLES
-These are the currently configurable items for
-.Xr gotweb 8
-with their default values.
-.Bd -literal -offset indent
-
-#
-# gotweb options
-# all paths relative to /var/www (httpd chroot jail)
-#
-
-got_repos_path "/got/public"
-got_www_path "/gotweb"
-
-#got_max_repos 100
-#got_max_repos_display 25
-got_max_commits_display 50
-
-got_site_name "my public repos"
-got_site_owner "Got Owner"
-got_site_link "repos"
-
-got_logo "got.png"
-got_logo_url "https://gameoftrees.org"
-
-# on by default
-#got_show_site_owner off
-#got_show_repo_owner off
-#got_show_repo_age false
-#got_show_repo_description no
-#got_show_repo_cloneurl off
-.Ed
-.Sh SEE ALSO
-.Xr got 1 ,
-.Xr gotweb 8
blob - aa311d40d3fa8a2632f5b8c4acd5c1e933cc8c49 (mode 644)
blob + /dev/null
--- gotweb/gotweb.h
+++ /dev/null
-/*
- * Copyright (c) 2019, 2020 Tracey Emery <tracey@traceyemery.net>
- * Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef GOTWEB_H
-#define GOTWEB_H
-
-#include <stdbool.h>
-
-#define GOTWEB_CONF "/etc/gotweb.conf"
-#define GOTWEB_TMPL_DIR "/cgi-bin/gw_tmpl"
-#define GOTWEB "/cgi-bin/gotweb/gotweb"
-
-#define GOTWEB_GOT_DIR ".got"
-#define GOTWEB_GIT_DIR ".git"
-
-#define D_GOTWWW "/gotweb"
-#define D_GOTPATH "/got/public"
-#define D_SITENAME "Gotweb"
-#define D_SITEOWNER "Got Owner"
-#define D_SITELINK "Repos"
-#define D_GOTLOGO "got.png"
-#define D_GOTURL "https://gameoftrees.org"
-
-#define D_SHOWROWNER true
-#define D_SHOWSOWNER true
-#define D_SHOWAGE true
-#define D_SHOWDESC true
-#define D_SHOWURL true
-#define D_MAXREPO 0
-#define D_MAXREPODISP 25
-#define D_MAXSLCOMMDISP 10
-#define D_MAXCOMMITDISP 25
-
-#define BUFFER_SIZE 2048
-
-struct gotweb_config {
- char *got_repos_path;
- char *got_www_path;
- char *got_site_name;
- char *got_site_owner;
- char *got_site_link;
- char *got_logo;
- char *got_logo_url;
-
- size_t got_max_repos;
- size_t got_max_repos_display;
- size_t got_max_commits_display;
-
- bool got_show_site_owner;
- bool got_show_repo_owner;
- bool got_show_repo_age;
- bool got_show_repo_description;
- bool got_show_repo_cloneurl;
-};
-
-/*
- * Parse gotweb config file, if it exists
- * Load gotweb_config struct
- */
-const struct got_error* parse_gotweb_config(struct gotweb_config **,
- const char *);
-
-#endif /* GOTWEB_H */
blob - 5fd34708bd3654bc05060446ff5d55557747cfd3 (mode 644)
blob + /dev/null
--- gotweb/libexec/Makefile
+++ /dev/null
-SUBDIR = got-read-blob got-read-commit got-read-object got-read-tree \
- got-read-tag got-read-pack got-read-gitconfig got-read-gotconfig
-
-.include <bsd.subdir.mk>
blob - 85bee26728643214f5d4570f003572ac1fc36d05 (mode 644)
blob + /dev/null
--- gotweb/libexec/Makefile.inc
+++ /dev/null
-.include "../Makefile.inc"
-
-realinstall:
- if [ ! -d ${DESTDIR}${CHROOT_DIR}${LIBEXECDIR}/. ]; then \
- ${INSTALL} -d -o root -g daemon -m 755 \
- ${DESTDIR}${CHROOT_DIR}${LIBEXECDIR}; \
- fi
- ${INSTALL} ${INSTALL_COPY} -o root -g daemon -m 755 ${PROG} \
- ${DESTDIR}${CHROOT_DIR}${LIBEXECDIR}/${PROG}
-
-NOMAN = Yes
blob - 58d428b99c43b2fba80028b6233bcd4ff6c7e4a4 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-blob/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-blob
-SRCS= got-read-blob.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-blob
-
-.include <bsd.prog.mk>
blob - 669332cc8be5487a26cc868b873f782c7e351623 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-commit/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-commit
-SRCS= got-read-commit.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-commit
-
-.include <bsd.prog.mk>
blob - d81d4666fc3206a3008ddfc673992c5ec3265bd9 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-gitconfig/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-gitconfig
-SRCS= got-read-gitconfig.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c gitconfig.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-gitconfig
-
-.include <bsd.prog.mk>
blob - abc9574b7efb93c971c76b3576970c8c19ba0e14 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-gotconfig/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-gotconfig
-SRCS= got-read-gotconfig.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c parse.y pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib \
- -I${.CURDIR}/../../../libexec/got-read-gotconfig
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-gotconfig
-
-.include <bsd.prog.mk>
blob - 1c3afaf56bad757cf3c8b9574bc12521adbda7bb (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-object/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-object
-SRCS= got-read-object.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-object
-
-.include <bsd.prog.mk>
blob - 9c1bf08b6d1c6cea526cdb38361ef89dfce5bc32 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-pack/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-pack
-SRCS= got-read-pack.c delta.c error.c inflate.c object_cache.c \
- object_idset.c object_parse.c opentemp.c pack.c path.c \
- privsep.c sha1.c delta_cache.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-pack
-
-.include <bsd.prog.mk>
blob - 450ee15c54e4904304143c4129f1adf9fd085073 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-tag/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-tag
-SRCS= got-read-tag.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-tag
-
-.include <bsd.prog.mk>
blob - 20c0a23b3bf5a858afe4cd8a8e2d57c5194dd074 (mode 644)
blob + /dev/null
--- gotweb/libexec/got-read-tree/Makefile
+++ /dev/null
-.include "../../../got-version.mk"
-.include "../Makefile.inc"
-
-PROG= got-read-tree
-SRCS= got-read-tree.c error.c inflate.c object_parse.c \
- path.c privsep.c sha1.c pollfd.c
-
-CPPFLAGS = -I${.CURDIR}/../../../include -I${.CURDIR}/../../../lib
-LDADD = -lutil -lz
-DPADD = ${LIBZ} ${LIBUTIL}
-LDSTATIC = ${STATIC}
-
-.PATH: ${.CURDIR}/../../../lib ${.CURDIR}/../../../libexec/got-read-tree
-
-.include <bsd.prog.mk>
blob - e1d44725734b9a6babef6ed3ea9430e0c42150dd (mode 644)
blob + /dev/null
--- gotweb/parse.y
+++ /dev/null
-/*
- * Copyright (c) 2019, 2020 Tracey Emery <tracey@openbsd.org>
- * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
- * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
- * Copyright (c) 2001 Theo de Raadt. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-%{
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/queue.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "got_error.h"
-#include "gotweb.h"
-
-TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
-static struct file {
- TAILQ_ENTRY(file) entry;
- FILE *stream;
- char *name;
- size_t ungetpos;
- size_t ungetsize;
- u_char *ungetbuf;
- int eof_reached;
- int lineno;
-} *file, *topfile;
-static const struct got_error* pushfile(struct file**, const char *);
-int popfile(void);
-int yyparse(void);
-int yylex(void);
-int yyerror(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)))
- __attribute__((__nonnull__ (1)));
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int igetc(void);
-int lgetc(int);
-void lungetc(int);
-int findeol(void);
-
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entry;
- int used;
- int persist;
- char *nam;
- char *val;
-};
-
-int symset(const char *, const char *, int);
-int cmdline_symset(char *);
-char *symget(const char *);
-
-const struct got_error* gerror = NULL;
-struct gotweb_config *gw_conf;
-
-typedef struct {
- union {
- int64_t number;
- char *string;
- } v;
- int lineno;
-} YYSTYPE;
-
-%}
-
-%token GOT_WWW_PATH GOT_MAX_REPOS GOT_SITE_NAME GOT_SITE_OWNER GOT_SITE_LINK
-%token GOT_LOGO GOT_LOGO_URL GOT_SHOW_REPO_OWNER GOT_SHOW_REPO_AGE
-%token GOT_SHOW_REPO_DESCRIPTION GOT_MAX_REPOS_DISPLAY GOT_REPOS_PATH
-%token GOT_MAX_COMMITS_DISPLAY ERROR GOT_SHOW_SITE_OWNER
-%token GOT_SHOW_REPO_CLONEURL
-%token <v.string> STRING
-%token <v.number> NUMBER
-%type <v.number> boolean
-%%
-
-grammar : /* empty */
- | grammar '\n'
- | grammar main '\n'
- ;
-
-boolean : STRING {
- if (strcasecmp($1, "true") == 0 ||
- strcasecmp($1, "on") == 0 ||
- strcasecmp($1, "yes") == 0)
- $$ = 1;
- else if (strcasecmp($1, "false") == 0 ||
- strcasecmp($1, "off") == 0 ||
- strcasecmp($1, "no") == 0)
- $$ = 0;
- else {
- yyerror("invalid boolean value '%s'", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-main : GOT_REPOS_PATH STRING {
- gw_conf->got_repos_path = $2;
- }
- | GOT_WWW_PATH STRING {
- gw_conf->got_www_path = $2;
- }
- | GOT_MAX_REPOS NUMBER {
- if ($2 > 0)
- gw_conf->got_max_repos = $2;
- }
- | GOT_SITE_NAME STRING {
- gw_conf->got_site_name = $2;
- }
- | GOT_SITE_OWNER STRING {
- gw_conf->got_site_owner = $2;
- }
- | GOT_SITE_LINK STRING {
- gw_conf->got_site_link = $2;
- }
- | GOT_LOGO STRING {
- gw_conf->got_logo = $2;
- }
- | GOT_LOGO_URL STRING {
- gw_conf->got_logo_url = $2;
- }
- | GOT_SHOW_SITE_OWNER boolean {
- gw_conf->got_show_site_owner = $2;
- }
- | GOT_SHOW_REPO_OWNER boolean {
- gw_conf->got_show_repo_owner = $2;
- }
- | GOT_SHOW_REPO_AGE boolean {
- gw_conf->got_show_repo_age = $2;
- }
- | GOT_SHOW_REPO_DESCRIPTION boolean {
- gw_conf->got_show_repo_description = $2;
- }
- | GOT_SHOW_REPO_CLONEURL boolean {
- gw_conf->got_show_repo_cloneurl = $2;
- }
- | GOT_MAX_REPOS_DISPLAY NUMBER {
- if ($2 > 0)
- gw_conf->got_max_repos_display = $2;
- }
- | GOT_MAX_COMMITS_DISPLAY NUMBER {
- if ($2 > 0)
- gw_conf->got_max_commits_display = $2;
- }
- ;
-%%
-
-struct keywords {
- const char *k_name;
- int k_val;
-};
-
-int
-yyerror(const char *fmt, ...)
-{
- va_list ap;
- char *msg;
- char *err = NULL;
-
- va_start(ap, fmt);
- if (vasprintf(&msg, fmt, ap) == -1) {
- gerror = got_error_from_errno("vasprintf");
- return 0;
- }
- va_end(ap);
- if (asprintf(&err, "%s:%d: %s", file->name, yylval.lineno, msg) == -1) {
- gerror = got_error_from_errno("asprintf");
- return(0);
- }
- gerror = got_error_msg(GOT_ERR_PARSE_CONFIG, err);
- free(msg);
- return(0);
-}
-
-int
-kw_cmp(const void *k, const void *e)
-{
- return (strcmp(k, ((const struct keywords *)e)->k_name));
-}
-
-int
-lookup(char *s)
-{
- /* This has to be sorted always. */
- static const struct keywords keywords[] = {
- { "got_logo", GOT_LOGO },
- { "got_logo_url", GOT_LOGO_URL },
- { "got_max_commits_display", GOT_MAX_COMMITS_DISPLAY },
- { "got_max_repos", GOT_MAX_REPOS },
- { "got_max_repos_display", GOT_MAX_REPOS_DISPLAY },
- { "got_repos_path", GOT_REPOS_PATH },
- { "got_show_repo_age", GOT_SHOW_REPO_AGE },
- { "got_show_repo_cloneurl", GOT_SHOW_REPO_CLONEURL },
- { "got_show_repo_description", GOT_SHOW_REPO_DESCRIPTION },
- { "got_show_repo_owner", GOT_SHOW_REPO_OWNER },
- { "got_show_site_owner", GOT_SHOW_SITE_OWNER },
- { "got_site_link", GOT_SITE_LINK },
- { "got_site_name", GOT_SITE_NAME },
- { "got_site_owner", GOT_SITE_OWNER },
- { "got_www_path", GOT_WWW_PATH },
- };
- const struct keywords *p;
-
- p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
- sizeof(keywords[0]), kw_cmp);
-
- if (p)
- return (p->k_val);
- else
- return (STRING);
-}
-
-#define START_EXPAND 1
-#define DONE_EXPAND 2
-
-static int expanding;
-
-int
-igetc(void)
-{
- int c;
-
- while (1) {
- if (file->ungetpos > 0)
- c = file->ungetbuf[--file->ungetpos];
- else
- c = getc(file->stream);
-
- if (c == START_EXPAND)
- expanding = 1;
- else if (c == DONE_EXPAND)
- expanding = 0;
- else
- break;
- }
- return (c);
-}
-
-int
-lgetc(int quotec)
-{
- int c, next;
-
- if (quotec) {
- if ((c = igetc()) == EOF) {
- yyerror("reached end of file while parsing "
- "quoted string");
- if (file == topfile || popfile() == EOF)
- return (EOF);
- return (quotec);
- }
- return (c);
- }
-
- while ((c = igetc()) == '\\') {
- next = igetc();
- if (next != '\n') {
- c = next;
- break;
- }
- yylval.lineno = file->lineno;
- file->lineno++;
- }
-
- if (c == EOF) {
- /*
- * Fake EOL when hit EOF for the first time. This gets line
- * count right if last line in included file is syntactically
- * invalid and has no newline.
- */
- if (file->eof_reached == 0) {
- file->eof_reached = 1;
- return ('\n');
- }
- while (c == EOF) {
- if (file == topfile || popfile() == EOF)
- return (EOF);
- c = igetc();
- }
- }
- return (c);
-}
-
-void
-lungetc(int c)
-{
- if (c == EOF)
- return;
-
- if (file->ungetpos >= file->ungetsize) {
- void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
- if (p == NULL)
- err(1, "%s", __func__);
- file->ungetbuf = p;
- file->ungetsize *= 2;
- }
- file->ungetbuf[file->ungetpos++] = c;
-}
-
-int
-findeol(void)
-{
- int c;
-
- /* Skip to either EOF or the first real EOL. */
- while (1) {
- c = lgetc(0);
- if (c == '\n') {
- file->lineno++;
- break;
- }
- if (c == EOF)
- break;
- }
- return (ERROR);
-}
-
-int
-yylex(void)
-{
- char buf[8096];
- char *p, *val;
- int quotec, next, c;
- int token;
-
-top:
- p = buf;
- while ((c = lgetc(0)) == ' ' || c == '\t')
- ; /* nothing */
-
- yylval.lineno = file->lineno;
- if (c == '#')
- while ((c = lgetc(0)) != '\n' && c != EOF)
- ; /* nothing */
- if (c == '$' && !expanding) {
- while (1) {
- if ((c = lgetc(0)) == EOF)
- return (0);
-
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- if (isalnum(c) || c == '_') {
- *p++ = c;
- continue;
- }
- *p = '\0';
- lungetc(c);
- break;
- }
- val = symget(buf);
- if (val == NULL) {
- yyerror("macro '%s' not defined", buf);
- return (findeol());
- }
- p = val + strlen(val) - 1;
- lungetc(DONE_EXPAND);
- while (p >= val) {
- lungetc((unsigned char)*p);
- p--;
- }
- lungetc(START_EXPAND);
- goto top;
- }
-
- switch (c) {
- case '\'':
- case '"':
- quotec = c;
- while (1) {
- if ((c = lgetc(quotec)) == EOF)
- return (0);
- if (c == '\n') {
- file->lineno++;
- continue;
- } else if (c == '\\') {
- if ((next = lgetc(quotec)) == EOF)
- return (0);
- if (next == quotec || c == ' ' || c == '\t')
- c = next;
- else if (next == '\n') {
- file->lineno++;
- continue;
- } else
- lungetc(next);
- } else if (c == quotec) {
- *p = '\0';
- break;
- } else if (c == '\0') {
- yyerror("syntax error");
- return (findeol());
- }
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- *p++ = c;
- }
- yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
- err(1, "%s", __func__);
- return (STRING);
- }
-
-#define allowed_to_end_number(x) \
- (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
-
- if (c == '-' || isdigit(c)) {
- do {
- *p++ = c;
- if ((size_t)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && isdigit(c));
- lungetc(c);
- if (p == buf + 1 && buf[0] == '-')
- goto nodigits;
- if (c == EOF || allowed_to_end_number(c)) {
- const char *errstr = NULL;
-
- *p = '\0';
- yylval.v.number = strtonum(buf, LLONG_MIN,
- LLONG_MAX, &errstr);
- if (errstr) {
- yyerror("\"%s\" invalid number: %s",
- buf, errstr);
- return (findeol());
- }
- return (NUMBER);
- } else {
-nodigits:
- while (p > buf + 1)
- lungetc((unsigned char)*--p);
- c = (unsigned char)*--p;
- if (c == '-')
- return (c);
- }
- }
-
-#define allowed_in_string(x) \
- (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && \
- x != '!' && x != '=' && x != '#' && \
- x != ','))
-
- if (isalnum(c) || c == ':' || c == '_') {
- do {
- *p++ = c;
- if ((size_t)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
- lungetc(c);
- *p = '\0';
- if ((token = lookup(buf)) == STRING)
- if ((yylval.v.string = strdup(buf)) == NULL)
- err(1, "%s", __func__);
- return (token);
- }
- if (c == '\n') {
- yylval.lineno = file->lineno;
- file->lineno++;
- }
- if (c == EOF)
- return (0);
- return (c);
-}
-
-static const struct got_error*
-pushfile(struct file **nfile, const char *name)
-{
- const struct got_error* error = NULL;
-
- if (((*nfile) = calloc(1, sizeof(struct file))) == NULL)
- return got_error_from_errno2(__func__, "calloc");
- if (((*nfile)->name = strdup(name)) == NULL) {
- free(*nfile);
- return got_error_from_errno2(__func__, "strdup");
- }
- if (((*nfile)->stream = fopen((*nfile)->name, "re")) == NULL) {
- char *msg = NULL;
- if (asprintf(&msg, "%s", (*nfile)->name) == -1)
- return got_error_from_errno("asprintf");
- error = got_error_msg(GOT_ERR_NO_CONFIG_FILE, msg);
- free((*nfile)->name);
- free((*nfile));
- free(msg);
- return error;
- }
- (*nfile)->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
- (*nfile)->ungetsize = 16;
- (*nfile)->ungetbuf = malloc((*nfile)->ungetsize);
- if ((*nfile)->ungetbuf == NULL) {
- fclose((*nfile)->stream);
- free((*nfile)->name);
- free((*nfile));
- return got_error_from_errno2(__func__, "malloc");
- }
- TAILQ_INSERT_TAIL(&files, (*nfile), entry);
- return error;
-}
-
-int
-popfile(void)
-{
- struct file *prev = NULL;
-
- TAILQ_REMOVE(&files, file, entry);
- fclose(file->stream);
- free(file->name);
- free(file->ungetbuf);
- free(file);
- file = prev;
- return (file ? 0 : EOF);
-}
-
-const struct got_error*
-parse_gotweb_config(struct gotweb_config **gconf, const char *filename)
-{
- gw_conf = malloc(sizeof(struct gotweb_config));
- if (gw_conf == NULL) {
- gerror = got_error_from_errno("malloc");
- goto done;
- }
- gw_conf->got_repos_path = strdup(D_GOTPATH);
- if (gw_conf->got_repos_path == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_www_path = strdup(D_GOTWWW);
- if (gw_conf->got_www_path == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_site_name = strdup(D_SITENAME);
- if (gw_conf->got_site_name == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_site_owner = strdup(D_SITEOWNER);
- if (gw_conf->got_site_owner == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_site_link = strdup(D_SITELINK);
- if (gw_conf->got_site_link == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_logo = strdup(D_GOTLOGO);
- if (gw_conf->got_logo == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_logo_url = strdup(D_GOTURL);
- if (gw_conf->got_logo_url == NULL) {
- gerror = got_error_from_errno("strdup");
- goto done;
- }
- gw_conf->got_show_site_owner = D_SHOWSOWNER;
- gw_conf->got_show_repo_owner = D_SHOWROWNER;
- gw_conf->got_show_repo_age = D_SHOWAGE;
- gw_conf->got_show_repo_description = D_SHOWDESC;
- gw_conf->got_show_repo_cloneurl = D_SHOWURL;
- gw_conf->got_max_repos = D_MAXREPO;
- gw_conf->got_max_repos_display = D_MAXREPODISP;
- gw_conf->got_max_commits_display = D_MAXCOMMITDISP;
-
- /*
- * We don't require that the gotweb config file exists
- * So reset gerror if it doesn't exist and goto done.
- */
- gerror = pushfile(&file, filename);
- if (gerror && gerror->code == GOT_ERR_NO_CONFIG_FILE) {
- gerror = NULL;
- goto done;
- } else if (gerror)
- return gerror;
- topfile = file;
-
- yyparse();
- popfile();
-done:
- *gconf = gw_conf;
- return gerror;
-}
-
-int
-symset(const char *nam, const char *val, int persist)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry) {
- if (strcmp(nam, sym->nam) == 0)
- break;
- }
-
- if (sym != NULL) {
- if (sym->persist == 1)
- return (0);
- else {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
- if ((sym = calloc(1, sizeof(*sym))) == NULL)
- return (-1);
-
- sym->nam = strdup(nam);
- if (sym->nam == NULL) {
- free(sym);
- return (-1);
- }
- sym->val = strdup(val);
- if (sym->val == NULL) {
- free(sym->nam);
- free(sym);
- return (-1);
- }
- sym->used = 0;
- sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entry);
- return (0);
-}
-
-int
-cmdline_symset(char *s)
-{
- char *sym, *val;
- int ret;
- size_t len;
-
- if ((val = strrchr(s, '=')) == NULL)
- return (-1);
-
- len = strlen(s) - strlen(val) + 1;
- if ((sym = malloc(len)) == NULL)
- errx(1, "cmdline_symset: malloc");
-
- strlcpy(sym, s, len);
-
- ret = symset(sym, val + 1, 1);
- free(sym);
-
- return (ret);
-}
-
-char *
-symget(const char *nam)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry) {
- if (strcmp(nam, sym->nam) == 0) {
- sym->used = 1;
- return (sym->val);
- }
- }
- return (NULL);
-}
blob - 3b4eac348bb9ce1af38f8f5b5a1aeb8f54b83e14
blob + 82afa2028dd0be74054dd2348115d8cc87611e14
--- util/got-build-regress.sh
+++ util/got-build-regress.sh
exit 0
fi
log_cmd build.log make install
-log_cmd build.log make -j $ncpu web
+log_cmd build.log make -j $ncpu webd
build_status="$?"
if [ "$build_status" != "0" ]; then
mail $fromaddr_arg -s "$prog build failure" $recipients < build.log
log_cmd build.log make clean
log_cmd build.log make obj
log_cmd build.log make -j $ncpu GOT_RELEASE=Yes
-log_cmd build.log make -j $ncpu GOT_RELEASE=Yes web
+log_cmd build.log make -j $ncpu GOT_RELEASE=Yes webd
build_status="$?"
if [ "$build_status" != "0" ]; then
mail $fromaddr_arg -s "$prog release mode build failure" $recipients < build.log