3 # format-readme -- find and format a repository's readme blob
4 # Copyright (C) 2015,2016 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/>.
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 it's 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.
44 if [ "$1" = "-r" -o "$1" = "-p" ]; then
46 [ "$1" != "-p" ] || addpath
=1
51 if [ "$1" = "-i" ]; then
59 [ -n "$projdir" -a -d "$projdir" ] ||
exit 2
60 cd "$projdir" ||
exit 2
62 gd
="$(git rev-parse --git-dir 2>&1)" ||
exit 2
65 tree
="$(git rev-parse --quiet --verify "$treeish"^{tree} 2>/dev/null)" ||
exit 2
67 # We prefer the first file or symlink we find with
68 # a supported extension and then we will follow it
69 # if it's a relative symlink with no '.' or '..' components.
70 # If we don't find a supported extension, we use just plain README
71 # which we assume to be plain text (and we will follow a symlink).
72 # We prefer a markdown extension over others and any extension
73 # other than plain text next followed by plain text and then no extension.
76 ! perl
-MPod::Html
-e 1 >/dev
/null
2>&1 || haspod
=1
88 while read -r mode
type hash size name
; do
89 [ "$mode" = "100644" -o "$mode" = "100755" -o "$mode" = "120000" ] ||
continue
90 [ "$size" != "0" -a "$size" != "-" ] ||
continue
91 [ "$type" = "blob" ] ||
continue
92 [ "$mode" != "120000" -o "$size" -lt 1024 ] ||
continue
93 [ "$mode" != "120000" ] || symlinks
="$symlinks$hash $name$nl"
96 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Mm
][Dd
]|\
97 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Mm
][Kk
][Dd
][Nn
]|\
98 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Mm
][Dd
][Oo
][Ww
][Nn
]|\
99 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Mm
][Aa
][Rr
][Kk
][Dd
][Oo
][Ww
][Nn
])
100 if [ -n "$readmeext" ]; then
101 [ "$readmeextfmt" != "md" -o "$mode" != "120000" ] ||
continue
106 [ "$mode" != "120000" ] || readmeextlnk
=1
110 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Pp
][Oo
][Dd
])
111 [ -n "$haspod" ] ||
continue
112 if [ -n "$readmeext" ]; then
113 [ "$readmeextfmt" != "md" ] ||
continue
114 [ "$readmeextfmt" = "txt" -o "$mode" != "120000" ] ||
continue
119 [ "$mode" != "120000" ] || readmeextlnk
=1
123 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Tt
][Xx
][Tt
]|\
124 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].
[Tt
][Ee
][Xx
][Tt
])
125 if [ -n "$readmeext" ]; then
126 [ "$readmeextfmt" = "txt" -a "$mode" != "120000" ] ||
continue
131 [ "$mode" != "120000" ] || readmeextlnk
=1
135 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
])
136 [ -z "$readme" -o "$mode" != "120000" ] ||
continue
140 [ "$mode" != "120000" ] || readmelnk
=1
143 [Rr
][Ee
][Aa
][Dd
][Mm
][Ee
].?
*)
144 [ -z "$readmefb" -o "$mode" != "120000" ] ||
continue
145 [ "${name%.*}" = "${name%%.*}" ] ||
continue
146 [ "${name#*.}" = "${name##*[!A-Za-z0-9+_]}" ] ||
continue
147 [ "${name%[$ws]*}" = "$name" ] ||
continue
151 [ "$mode" != "120000" ] || readmefblnk
=1
156 $(git ls-tree -l $tree)
158 if [ -n "$readmefb" -a -z "$readme" ]; then
160 readmenm
="$readmefbnm"
161 readmelnk
="$readmefblnk"
163 if [ -n "$readme" -a -z "$readmeext" ]; then
165 readmeextnm
="$readmenm"
166 readmeextlnk
="$readmelnk"
169 [ -n "$readmeext" ] ||
exit 1
170 if [ -n "$readmeextlnk" ]; then
171 rel
="$(git cat-file blob $readmeext 2>/dev/null)" ||
exit 1
172 case "$rel" in /*) exit 1; esac
173 case "/$rel/" in */..
/*|
*/.
/*) exit 1; esac
174 case "$rel" in */*) :;; ?
*)
175 while read -r hash name
; do
176 if [ -n "$hash" -a "$name" = "$rel" ]; then
177 rel2
="$(git cat-file blob $hash 2>/dev/null)" ||
exit 1
178 case "$rel2" in /*) exit 1; esac
179 case "/$rel2/" in */..
/*|
*/.
/*) exit 1; esac
187 case "$rel" in *?
/?
*)
189 prefix
="${rel%/$suffix}"
190 while read -r hash name
; do
191 if [ -n "$hash" -a "$name" = "$prefix" ]; then
192 rel2
="$(git cat-file blob $hash 2>/dev/null)" ||
exit 1
193 case "$rel2" in /*) exit 1; esac
194 case "/$rel2/" in */..
/*|
*/.
/*) exit 1; esac
202 if [ -n "$addpath" ]; then
203 dir
="$(dirname "$rel")"
204 if [ "$dir" != "." ]; then
205 urlprefix
="${urlprefix%/}/$dir"
206 [ -z "$imgprefix" ] || imgprefix
="${imgprefix%/}/$dir"
209 read -r mode
type hash size name
<<EOT
210 $(git ls-tree -l $tree -- "$rel")
212 [ "$mode" = "100644" -o "$mode" = "100755" ] ||
exit 1
213 [ "$type" = "blob" ] ||
exit 1
214 [ "$size" != "0" -a "$size" != "-" ] ||
exit 1
216 [ "$size" -le 32768 ] ||
exit 1
220 # Allow up to 32K, but fail if it doesn't look like it's text.
222 contents
="$(git cat-file blob $readmeext | perl -e '
226 binmode STDIN, ":perlio
" or exit 1
227 unless grep /^perlio$/, PerlIO::get_layers(STDIN);
228 exit 1 unless -T STDIN;
230 my $contents = <STDIN>;
231 exit 1 unless defined($contents) && length($contents) > 0 && length($contents) <= 32768;
234 ' 2>/dev/null)" ||
exit 1
237 case "$readmeextfmt" in
240 # Run Markdown.pl on it
242 if [ -n "$addprefix" ]; then
243 cmd
="$cmd -r \"$urlprefix\""
244 [ -z "$imgprefix" ] || cmd
="$cmd -i \"$imgprefix\""
246 printf '<!-- README NAME: %s -->\n' "$readmeextnm"
247 printf '%s' "$contents" |
eval "$cmd 2>/dev/null"
252 # Run pod2html and extract the contents
254 if [ -n "$addprefix" -a -n "${urlprefix%/}" ]; then
255 arg
=", \"--htmlroot=${urlprefix%/}\""
257 printf '<!-- README NAME: %s -->\n' "$readmeextnm"
258 printf '%s' "$contents" | \
259 perl
-MPod::Html
-e "pod2html \"--quiet\", \"--no-index\"$arg" 2>/dev
/null | \
264 my $contents = <STDIN>;
265 $contents =~ s,^.*<body[^>]*>\s*,,is;
266 $contents =~ s,\s*</body[^>]*>.*$,,is;
267 $contents =~ s,^.*<!--\s*INDEX\s+END\s*-->\s*,,is;
268 $contents =~ s,^\s*(?:<p>\s*</p>\s*)+,,is;
275 # It's a <pre> block but we need some escaping
276 printf '<!-- README NAME: %s -->\n' "$readmeextnm"
277 printf '%s' '<pre class="plaintext">'
278 printf '%s' "$contents" | LC_ALL
=C
sed -e 's/&/\&/g' -e 's/</\</g'
279 printf '%s\n' '</pre>'