first commit
This commit is contained in:
commit
32c540a903
5 changed files with 333 additions and 0 deletions
26
Makefile
Normal file
26
Makefile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
DEPS = utf8 lowdown
|
||||||
|
SRC = main.scm
|
||||||
|
DIR_INSTALL ?= /usr/local/bin
|
||||||
|
DIR_BUILD = .
|
||||||
|
BIN = repo2html
|
||||||
|
|
||||||
|
all: compile
|
||||||
|
|
||||||
|
compile:
|
||||||
|
mkdir $(DIR_BUILD)/
|
||||||
|
csc -O3 -static ./$(SRC) -o $(DIR_BUILD)/$(BIN)
|
||||||
|
rm ./$(DIR_BUILD)/$(BIN).link
|
||||||
|
@echo "Finished compiling a static binary in $(DIR_BUILD)/$(BIN)!"
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
chicken-install $(DEPS)
|
||||||
|
|
||||||
|
install:
|
||||||
|
install -Dm755 $(DIR_BUILD)/$(BIN) -D $(DIR_INSTALL)/$(PROG)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm $(DIR_INSTALL)/$(PROG)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm $(DIR_BUILD)/$(BIN)
|
||||||
|
|
55
README.md
Normal file
55
README.md
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# repo2html
|
||||||
|
|
||||||
|
a tool that generates an html view of a git repository.
|
||||||
|
|
||||||
|
## features
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## caveats
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## disclaimer
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## requirements
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## quickstart
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## compilation
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo make dependencies
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
## installation
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## post installation
|
||||||
|
|
||||||
|
TODO (git user, ssh, ufw ports, web directory, git-daemon, mkdir /home/git/projects, post-receive hook, systemd service)
|
||||||
|
|
||||||
|
## usage
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## configuration
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## todos
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## hopes
|
||||||
|
|
||||||
|
TODO
|
15
git-daemon.service
Normal file
15
git-daemon.service
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Start Git Daemon
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/git daemon --base-path=/home/git/projects --export-all --reuseaddr --informative-errors --verbose
|
||||||
|
Restart=always
|
||||||
|
RestartSec=500ms
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
SyslogIdentifier=git-daemon
|
||||||
|
User=git
|
||||||
|
Group=git
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
226
main.scm
Normal file
226
main.scm
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
;; how to use this script
|
||||||
|
;; 1. cd into a bare git repository
|
||||||
|
;; 2. run the following, changing any values you want:
|
||||||
|
;; export GIT_WWW=/var/www/git/ GIT_WWW_CLONE_URL=git://git.m455.casa GIT_WWW_TITLE=git.m455.casa GIT_WWW_DESCRIPTION="m455's git repositories" GIT_WWW_H1=git.m455.casa; csi -s ../main.scm
|
||||||
|
;; i figured i would use environment variables instead of a config file,
|
||||||
|
;; because folks are just going to run this as a post-receive hook anyway, so
|
||||||
|
;; why not all just configure it all in the post-receive hook like so?
|
||||||
|
;; (assuming git-www is in your $PATH, and assuming git-www is a compiled
|
||||||
|
;; version of git-www.scm):
|
||||||
|
;; ---------------------------------
|
||||||
|
;; #!/bin/sh
|
||||||
|
;; export GIT_WWW=/var/www/git/
|
||||||
|
;; export GIT_WWW_CLONE_URL=git://git.m455.casa
|
||||||
|
;; export GIT_WWW_TITLE=git.m455.casa
|
||||||
|
;; export GIT_WWW_DESCRIPTION="m455's git repositories"
|
||||||
|
;; export GIT_WWW_H1=git.m455.casa
|
||||||
|
;; git-www
|
||||||
|
;; ---------------------------------
|
||||||
|
|
||||||
|
;; TODO:
|
||||||
|
;; [x] replace all repository-name with *repository-name*
|
||||||
|
;; [x] replace all repository-directory with *repository-directory*
|
||||||
|
;; [x] remove all passed around parameters for repo name and directory
|
||||||
|
;; [x] move html-body-contents into final html-template format except use
|
||||||
|
;; string translate for named variables in the html-template
|
||||||
|
;; Nice-to-haves:
|
||||||
|
;; [ ] nav link: License (look for LICENSE file)
|
||||||
|
;; [ ] nav link: Contributors
|
||||||
|
;; [ ] nav link: Releases
|
||||||
|
;; [ ] clickable line numbers in source files
|
||||||
|
;; [ ] render images
|
||||||
|
;; [ ] make repos with more files and directories less daunting (recursively generate a files list page for each directory in a repo?)
|
||||||
|
(import utf8
|
||||||
|
lowdown
|
||||||
|
(chicken string)
|
||||||
|
(chicken port)
|
||||||
|
(chicken io)
|
||||||
|
(chicken process)
|
||||||
|
(chicken process-context)
|
||||||
|
(chicken format)
|
||||||
|
(chicken pathname)
|
||||||
|
(chicken file))
|
||||||
|
|
||||||
|
;; decided to make these two buggers globals because i passed them around
|
||||||
|
;; between functions so much
|
||||||
|
(define *repository-name* #f)
|
||||||
|
(define *repository-directory* #f)
|
||||||
|
|
||||||
|
(define WEB-DIRECTORY (let ((environment-variable (get-environment-variable "GIT_WWW")))
|
||||||
|
;; this seems silly, but i'm not sure how else i should do it haha
|
||||||
|
(if environment-variable environment-variable "/var/www/git")))
|
||||||
|
|
||||||
|
(define CLONE-URL (let ((environment-variable (get-environment-variable "GIT_WWW_CLONE_URL")))
|
||||||
|
;; this seems silly, but i'm not sure how else i should do it haha
|
||||||
|
(if environment-variable environment-variable "git://git.example.com")))
|
||||||
|
|
||||||
|
(define TITLE (let ((environment-variable (get-environment-variable "GIT_WWW_TITLE")))
|
||||||
|
(if environment-variable environment-variable "my git repositories")))
|
||||||
|
|
||||||
|
(define DESCRIPTION (let ((environment-variable (get-environment-variable "GIT_WWW_DESCRIPTION")))
|
||||||
|
(if environment-variable environment-variable "my git repositories")))
|
||||||
|
|
||||||
|
(define H1 (let ((environment-variable (get-environment-variable "GIT_WWW_H1")))
|
||||||
|
(if environment-variable environment-variable "git.example.com")))
|
||||||
|
|
||||||
|
(define HTML-TEMPLATE
|
||||||
|
#<<string-block
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>{{title}}</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||||
|
<link rel="icon" href="data:,">
|
||||||
|
<meta name="description" content="{{description}}"/>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 700px;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
background-color: pink;
|
||||||
|
padding: 15px 20px;
|
||||||
|
white-space: pre;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
a { color: blue; }
|
||||||
|
nav a { margin-right: 10px; }
|
||||||
|
hr {
|
||||||
|
border:0;
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
#file-path {
|
||||||
|
/* change this to your liking */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{{h1}}</h1>
|
||||||
|
<h2>{{repository-name}}</h2>
|
||||||
|
<p>clone url: {{clone-url}}/{{repository-name}}</p>
|
||||||
|
<nav>
|
||||||
|
<a href="/{{repository-name}}/index.html">about</a>
|
||||||
|
<a href="/{{repository-name}}/files.html">files</a>
|
||||||
|
</nav>
|
||||||
|
<hr>
|
||||||
|
{{body-contents}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
string-block
|
||||||
|
)
|
||||||
|
|
||||||
|
(define (write-file file contents)
|
||||||
|
(with-output-to-file file (lambda () (display contents))))
|
||||||
|
|
||||||
|
(define (populate-html-template body-contents)
|
||||||
|
(string-translate*
|
||||||
|
HTML-TEMPLATE
|
||||||
|
`(
|
||||||
|
("{{title}}" . ,TITLE)
|
||||||
|
("{{description}}" . ,DESCRIPTION)
|
||||||
|
("{{h1}}" . ,H1)
|
||||||
|
("{{clone-url}}" . ,CLONE-URL)
|
||||||
|
("{{repository-name}}" . ,*repository-name*)
|
||||||
|
("{{body-contents}}" . ,body-contents))))
|
||||||
|
|
||||||
|
(define (in-git-directory?)
|
||||||
|
(if (equal? (call-with-input-pipe "git rev-parse --is-bare-repository 2> /dev/null" read-line) "true")
|
||||||
|
#t
|
||||||
|
#f))
|
||||||
|
|
||||||
|
(define (get-repository-name)
|
||||||
|
(pathname-strip-directory (current-directory)))
|
||||||
|
; (call-with-input-pipe "git config --get remote.origin.url" read-line)))
|
||||||
|
|
||||||
|
(define (git-repository->paths-list)
|
||||||
|
(call-with-input-pipe "git ls-tree -r --name-only HEAD" read-lines))
|
||||||
|
|
||||||
|
(define (git-file->string path)
|
||||||
|
(string-intersperse
|
||||||
|
(call-with-input-pipe (format "git show HEAD:~a" path) read-lines)
|
||||||
|
"\n"))
|
||||||
|
|
||||||
|
|
||||||
|
(define (clean-html str)
|
||||||
|
(string-translate* str '(("&" . "&")
|
||||||
|
("<" . "<")
|
||||||
|
(">" . ">")
|
||||||
|
("\"" . """)
|
||||||
|
("'" . "'"))))
|
||||||
|
|
||||||
|
(define (md->html markdown-string)
|
||||||
|
(with-output-to-string
|
||||||
|
(lambda ()
|
||||||
|
(markdown->html markdown-string))))
|
||||||
|
|
||||||
|
(define (generate-list-of-files source-files-list)
|
||||||
|
(if (null? source-files-list)
|
||||||
|
""
|
||||||
|
(let* ((source-file (car source-files-list))
|
||||||
|
(link-url (string-append source-file ".html"))) ;; src/main.scm.html
|
||||||
|
(string-append (format "<li><a href=\"~a\">~a</a></li>\n" link-url source-file)
|
||||||
|
(generate-list-of-files (cdr source-files-list))))))
|
||||||
|
|
||||||
|
(define (generate-source-file source-file) ;; src/main.scm
|
||||||
|
(let* ((source-file-directory (pathname-directory source-file)) ;; src or #f
|
||||||
|
(output-directory (if source-file-directory
|
||||||
|
(make-pathname *repository-directory* source-file-directory) ;; <WEB-DIRECTORY>/<repository-name>/src
|
||||||
|
*repository-directory*))) ;; <WEB-DIRECTORY>/<repository-name>
|
||||||
|
;; create directories that mimic the path of the source file, so when
|
||||||
|
;; someone clicks a link to view the contents of a source file, the URL
|
||||||
|
;; matches up with the path of the source file.
|
||||||
|
;; i guess another reason to do this is to avoid conflicts with files that
|
||||||
|
;; have the same name, but exist in different directories.
|
||||||
|
(create-directory output-directory #t)
|
||||||
|
(write-file
|
||||||
|
(make-pathname output-directory (pathname-strip-directory source-file) "html")
|
||||||
|
(populate-html-template (string-append "<p id=\"file-path\">" source-file "</p>"
|
||||||
|
"<pre>\n"
|
||||||
|
(clean-html (git-file->string source-file))
|
||||||
|
"</pre>")))))
|
||||||
|
|
||||||
|
(define (generate-source-files source-files-list)
|
||||||
|
(for-each (lambda (source-file) (generate-source-file source-file))
|
||||||
|
source-files-list))
|
||||||
|
|
||||||
|
(define (generate-files-file files-list-page-path source-files-list)
|
||||||
|
(write-file
|
||||||
|
files-list-page-path
|
||||||
|
(populate-html-template (string-append "<ul>\n"
|
||||||
|
(generate-list-of-files source-files-list)
|
||||||
|
"</ul>\n"))))
|
||||||
|
|
||||||
|
(define (generate-readme-file index-page-path)
|
||||||
|
(write-file
|
||||||
|
index-page-path
|
||||||
|
(populate-html-template (md->html (git-file->string "README.md")))))
|
||||||
|
|
||||||
|
(define (generate-repository-directory)
|
||||||
|
(if (directory-exists? *repository-directory*)
|
||||||
|
(begin (delete-directory *repository-directory* #t)
|
||||||
|
(create-directory *repository-directory* #t))
|
||||||
|
(create-directory *repository-directory* #t)))
|
||||||
|
|
||||||
|
(define (generate-html-files)
|
||||||
|
(let ((source-files-list (git-repository->paths-list)))
|
||||||
|
(generate-repository-directory)
|
||||||
|
(generate-readme-file (make-pathname *repository-directory* "index.html"))
|
||||||
|
(generate-files-file (make-pathname *repository-directory* "files.html") source-files-list)
|
||||||
|
(generate-source-files source-files-list)))
|
||||||
|
|
||||||
|
(define (if-git-directory-generate-html-files)
|
||||||
|
(if (in-git-directory?)
|
||||||
|
(begin (set! *repository-name* (get-repository-name))
|
||||||
|
(set! *repository-directory* (make-pathname WEB-DIRECTORY *repository-name*))
|
||||||
|
(generate-html-files))
|
||||||
|
(print "woops that's not a git directory")))
|
||||||
|
|
||||||
|
(define (main args)
|
||||||
|
(if (null? args)
|
||||||
|
(if-git-directory-generate-html-files)
|
||||||
|
(print "woops, i dont take args")))
|
||||||
|
|
||||||
|
(main (command-line-arguments))
|
||||||
|
|
11
post-receive.sample
Executable file
11
post-receive.sample
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# place this file in the 'hooks' directory of a bare git repository
|
||||||
|
# this assumes that repo2html is in your path
|
||||||
|
|
||||||
|
export GIT_WWW=/var/www/git/
|
||||||
|
export GIT_WWW_CLONE_URL=git://git.m455.casa
|
||||||
|
export GIT_WWW_TITLE=git.m455.casa
|
||||||
|
export GIT_WWW_DESCRIPTION="m455's git repositories"
|
||||||
|
export GIT_WWW_H1=git.m455.casa
|
||||||
|
repo2html
|
Loading…
Reference in a new issue