ref updates: switch from ref-change to ref-changes
[girocco.git] / bin / format-readme
blob52bec86d47682999839948f28c5a6a8def36b0dd
1 #!/bin/sh
3 # format-readme -- find and format a repository's readme blob
4 # Copyright (C) 2015 Kyle J. McKay. All rights reserved.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # Version 1.2.1
21 # Usage: format-readme [-r <prefix> | -p <prefix> [ -i <imgprefix ] ]
22 # <path-to-repo.git> [<treeish>]
24 # With -r <prefix>, prefix all non-absolute URLs with <prefix>
26 # With -p <prefix>, prefix all non-aboslute URLs with <prefix>/<symlink-path>
27 # where <symlink-path> is the dirname portion of symlink if the selected readme
28 # is a symlink that needs to be followed. If it's not a symlink or its in the
29 # same directory, the "/<symlink-path>" is not added but <prefix> still is.
31 # With -i <imgprefix> use <imgprefix> instead of <prefix> when link is to
32 # an image. If -p was used it will include the path, if -r was used it won't.
34 set -e
36 addprefix=
37 addpath=
38 urlprefix=
39 imgprefix=
40 if [ "$1" = "-r" -o "$1" = "-p" ]; then
41 addprefix=1
42 [ "$1" != "-p" ] || addpath=1
43 shift
44 [ -n "$1" ] || exit 2
45 urlprefix="${1%/}/"
46 shift
47 if [ "$1" = "-i" ]; then
48 shift
49 [ -n "$1" ] || exit 2
50 imgprefix="${1%/}/"
51 shift
54 projdir="$1"
55 [ -n "$projdir" -a -d "$projdir" ] || exit 2
56 cd "$projdir" || exit 2
57 unset GIT_DIR
58 gd="$(git rev-parse --git-dir 2>&1)" || exit 2
59 cd "$gd" || exit 2
60 treeish="${2:-HEAD}"
61 tree="$(git rev-parse --quiet --verify "$treeish"^{tree} 2>/dev/null)" || exit 2
63 # We prefer the first file or symlink we find with
64 # a supported extension and then we will follow it
65 # if it's a relative symlink with no '.' or '..' components.
66 # If we don't find a supported extension, we use just plain README
67 # which we assume to be plain text (and we will follow a symlink).
68 # We prefer a markdown extension over others and any extension
69 # other than plain text next followed by plain text and then no extension.
71 haspod=
72 ! perl -MPod::Html -e 1 >/dev/null 2>&1 || haspod=1
74 readme=
75 readmelnk=
76 readmeext=
77 readmeextlnk=
78 readmeextfmt=
79 while read -r mode type hash name; do
80 [ "$mode" = "100644" -o "$mode" = "100755" -o "$mode" = "120000" ] || continue
81 [ "$type" = "blob" ] || continue
82 case "$name" in
84 readme.md|readme.markdown)
85 if [ -n "$readmeext" ]; then
86 [ "$readmeextfmt" != "md" -o "$mode" != "120000" ] || continue
88 readmeext="$hash"
89 readmeextlnk=
90 [ "$mode" != "120000" ] || readmeextlnk=1
91 readmeextfmt=md
94 readme.pod)
95 [ -n "$haspod" ] || continue
96 if [ -n "$readmeext" ]; then
97 [ "$readmeextfmt" != "md" ] || continue
98 [ "$readmeextfmt" = "txt" -o "$mode" != "120000" ] || continue
100 readmeext="$hash"
101 readmeextlnk=
102 [ "$mode" != "120000" ] || readmeextlnk=1
103 readmeextfmt=pod
106 readme.txt|readme.text)
107 if [ -n "$readmeext" ]; then
108 [ "$readmeextfmt" = "txt" -a "$mode" != "120000" ] || continue
110 readmeext="$hash"
111 readmeextlnk=
112 [ "$mode" != "120000" ] || readmeextlnk=1
113 readmeextfmt=txt
116 readme)
117 [ -z "$readme" -o "$mode" != "120000" ] || continue
118 readme="$hash"
119 readmelnk=
120 [ "$mode" != "120000" ] || readmelnk=1
123 esac
124 done <<EOT
125 $(git ls-tree $tree | LC_ALL=C tr A-Z a-z)
127 if [ -n "$readme" -a -z "$readmeext" ]; then
128 readmeext="$readme"
129 readmeextlnk="$readmelnk"
130 readmeextfmt=txt
132 [ -n "$readmeext" ] || exit 1
133 if [ -n "$readmeextlnk" ]; then
134 rel="$(git cat-file blob $readmeext 2>/dev/null)" || exit 1
135 case "$rel" in /*) exit 1; esac
136 case "/$rel/" in */../*|*/./*) exit 1; esac
137 if [ -n "$addpath" ]; then
138 dir="$(dirname "$rel")"
139 if [ "$dir" != "." ]; then
140 urlprefix="${urlprefix%/}/$dir"
141 [ -z "$imgprefix" ] || imgprefix="${imgprefix%/}/$dir"
144 read -r mode type hash name <<EOT
145 $(git ls-tree $tree -- "$rel")
147 [ "$mode" = "100644" -o "$mode" = "100755" ] || exit 1
148 [ "$type" = "blob" ] || exit 1
149 readmeext="$hash"
152 # Get up to the first 32K, but fail if it doesn't look like
153 # it's text.
155 contents="$(git cat-file blob $readmeext | LC_ALL=C cut -b 1-32769 | perl -e '
156 use 5.008;
157 use strict;
158 use warnings;
159 binmode STDIN, ":perlio" or exit 1
160 unless grep /^perlio$/, PerlIO::get_layers(STDIN);
161 exit 1 unless -T STDIN;
162 undef $/;
163 my $contents = <STDIN>;
164 exit 1 unless defined($contents) && length($contents) > 0 && length($contents)<= 32768;
165 print $contents;
166 exit 0;
167 ' 2>/dev/null)" || exit 1
169 # Format the result
170 case "$readmeextfmt" in
173 # Run Markdown.pl on it
174 cmd='Markdown.pl'
175 if [ -n "$addprefix" ]; then
176 cmd="$cmd -r \"$urlprefix\""
177 [ -z "$imgprefix" ] || cmd="$cmd -i \"$imgprefix\""
179 printf '%s' "$contents" | eval "$cmd 2>/dev/null"
180 exit $?
183 pod)
184 # Run pod2html and extract the contents
185 arg=
186 if [ -n "$addprefix" -a -n "${urlprefix%/}" ]; then
187 arg=", \"--htmlroot=${urlprefix%/}\""
189 printf '%s' "$contents" | \
190 perl -MPod::Html -e "pod2html \"--quiet\", \"--no-index\"$arg" 2>/dev/null | \
191 perl -e '
192 use strict;
193 use warnings;
194 undef $/;
195 my $contents = <STDIN>;
196 $contents =~ s,^.*<body[^>]*>\s*,,is;
197 $contents =~ s,\s*</body[^>]*>.*$,,is;
198 $contents =~ s,^.*<!--\s*INDEX\s+END\s*-->\s*,,is;
199 $contents =~ s,^\s*(?:<p>\s*</p>\s*)+,,is;
200 print $contents;
202 exit $?
205 txt)
206 # It's a <pre> block but we need some escaping
207 printf '%s' '<pre class="plaintext">'
208 printf '%s' "$contents" | LC_ALL=C sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g'
209 printf '%s\n' '</pre>'
210 exit 0
213 esac
214 exit 1