about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorCase Duckworth2022-06-30 17:28:12 -0500
committerCase Duckworth2022-06-30 17:28:22 -0500
commit4308699484e91053b471f64fdf29149087d8cd75 (patch)
tree8fb16136763edb0b509339f4fbaf3dd88c9e2a5d
parentUpdate README (diff)
downloadlicensor-4308699484e91053b471f64fdf29149087d8cd75.tar.gz
licensor-4308699484e91053b471f64fdf29149087d8cd75.zip
Update to version 1.0
-rw-r--r--COPYING24
-rw-r--r--LICENSE19
-rw-r--r--Makefile19
-rwxr-xr-xlicenser181
-rwxr-xr-xlicensor251
5 files changed, 287 insertions, 207 deletions
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..0a06d2f --- /dev/null +++ b/COPYING
@@ -0,0 +1,24 @@
1
2Copyright (C) 2022 Case Duckworth <acdw@acdw.net>
3
4Permission is hereby granted, free of charge, to any person
5obtaining a copy of this software and associated documentation files
6(the "Software"), to deal in the Software without restriction,
7including without limitation the rights to use, copy, modify, merge,
8publish, distribute, sublicense, and/or sell copies of the Software,
9and to permit persons to whom the Software is furnished to do so,
10subject to the following conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23
24
diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 44c8493..0000000 --- a/LICENSE +++ /dev/null
@@ -1,19 +0,0 @@
1Copyright 2020 Case Duckworth
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is
8furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/Makefile b/Makefile index 6f7723b..cca469c 100644 --- a/Makefile +++ b/Makefile
@@ -1,15 +1,20 @@
1# licenser 1# licenser
2 2
3PREFIX ?= /usr 3PREFIX = /usr/local
4 4
5.PHONY: def install uninstall 5.PHONY: help install uninstall
6 6
7def: 7help:
8 @echo "run 'make install' to install" 8 @echo "licensor : drop urself a license"
9 @echo "run 'make uninstall' to uninstall" 9 @echo "(C) 2021--2022 Case Duckworth <acdw@acdw.net>"
10 @echo
11 @echo "TARGETS:"
12 @echo " install Install licensor to $(DESTDIR)$(PREFIX)/bin/licensor."
13 @echo " uninstall Uninstall licensor-related files."
10 14
11install: licenser 15install: licensor
12 install -D $< $(DESTDIR)$(PREFIX)/bin 16 install -D $< $(DESTDIR)$(PREFIX)/bin
13 17
14uninstall: 18uninstall:
15 rm -f $(DESTDIR)$(PREFIX)/bin/licenser 19 rm -f $(DESTDIR)$(PREFIX)/bin/licensor
20 rm -rf "${XDG_CACHE_HOME:-$HOME/.cache}/licensor"
diff --git a/licenser b/licenser deleted file mode 100755 index 2337470..0000000 --- a/licenser +++ /dev/null
@@ -1,181 +0,0 @@
1#!/bin/sh
2# licenser: drop a little ol license in there
3# Author: Case Duckworth <acdw@acdw.net>
4# License: MIT
5# Version: 0.2
6
7# Constants
8## where to download licenses from
9PRGN="${0##*/}"
10: "${LICENSER_SOURCE:=https://git.sr.ht/~acdw/licenser-licenses/blob/master}"
11LICENSER_CACHE="${XDG_DATA_HOME:-$HOME/.local/share}/licenser"
12LICENSER_LICENSE="${LICENSER_LICENSE:-MIT}"
13EXEC="${EXEC:-true}"
14
15usage() {
16 cat <<EOF
17$PRGN: plop a license in your project
18
19usage: $PRGN [-h|-m|-M]
20 $PRGN [-f] [-q] [-y YEAR] [-a AUTHOR] [-e EMAIL]
21 [-l LANG] [-o FILE] [LICENSE]
22flags:
23 -h show this help and exit
24 -m list available licenses and exit
25 -M list licenses, disregarding cached manifest
26 -f overwrite existing license
27 -q quiet: don't log anything
28options:
29 -y YEAR set copyright date(s) to YEAR.
30 default: \$(date +%Y).
31 this option accepts arbitrary input.
32 -a AUTHOR set copyright holder(s) to AUTHOR.
33 default:
34 - git config --get user.name
35 - getent password \$USER
36 - \$USER
37 -e EMAIL set AUTHOR's email address to EMAIL.
38 default:
39 - git config --get user.email
40 - [blank]
41 -l LANG set license language to LANG.
42 default: 'en' (subject to change)
43 -o FILE set output file to FILE.
44 default: LICENSE in \$PWD
45parameters:
46 LICENSE which license to use.
47 default: \$LICENSER_LICENSE, which
48 defaults to MIT.
49EOF
50}
51
52# entry point
53licenser() {
54 _force=false # don't replace licenses
55 _quiet=false # log stuff
56 __OUT=LICENSE # default output file
57 __LANG=en # default to en because it's got the most licenses XXX
58
59 while getopts hmMfqy:a:e:o:l:s: OPT; do
60 case "$OPT" in
61 h)
62 usage
63 exit 0
64 ;;
65 f) _force=true ;;
66 m)
67 list_licenses
68 exit "$?"
69 ;;
70 M)
71 list_licenses -f
72 exit "$?"
73 ;;
74 q) _quiet=true ;;
75 y) __YEAR="$OPTARG" ;;
76 a) __AUTHOR="$OPTARG" ;;
77 e) __EMAIL="$OPTARG" ;;
78 o) __OUT="$OPTARG" ;;
79 l) __LANG="$OPTARG" ;;
80 *)
81 usage
82 exit 1
83 ;;
84 esac
85 done
86 shift $((OPTIND - 1))
87 __LICENSE="${1:-$LICENSER_LICENSE}"
88
89 if ! __CACHED=$(get_license "$__LICENSE"); then
90 list_licenses
91 exit 2
92 fi
93
94 if [ -e "$__OUT" ] && ! $_force; then
95 log "File exists: $__OUT"
96 exit 3
97 fi
98
99 eval "$(
100 put "cat<<_END_LICENSE_"
101 cat "$__CACHED"
102 put
103 put "_END_LICENSE_"
104 )" >"$__OUT"
105
106 log "$__LICENSE written to $__OUT."
107}
108
109# download a license, or get it from the cache
110# if there's not one, return error
111get_license() {
112 license="$1"
113 cached="$LICENSER_CACHE/$license/$__LANG"
114 source="$LICENSER_SOURCE/$license/$__LANG"
115
116 mkdir -p "$LICENSER_CACHE/$license"
117 log "Checking cache for $license..."
118 if [ ! -f "$cached" ]; then
119 log "Not found. Downloading from $source..."
120 if ! curl -fLo "$cached" "$source"; then
121 log "License $license unavailable in language: $__LANG"
122 return 1
123 fi
124 fi
125 put "$cached"
126}
127
128# download a list of the licenses, or get it from the cache
129list_licenses() {
130 cached="$LICENSER_CACHE/manifest"
131 source="$LICENSER_SOURCE/manifest"
132
133 [ "x$1" = "x-r" ] && rm "$cached"
134
135 mkdir -p "$LICENSER_CACHE"
136 log "Checking cache for manifest..."
137 if [ ! -f "$cached" ]; then
138 log "Not found. Downloading from $source..."
139 if ! curl -fLo "$cached" "$LICENSER_SOURCE/manifest"; then
140 log "Unable to get the manifest"
141 return 1
142 fi
143 fi
144 cat "$cached"
145}
146
147# template function for the copyright year
148year() {
149 case "$__YEAR" in
150 '') # figure out the year
151 date +%Y ;;
152 *) # one was provided
153 put "$__YEAR" ;;
154 esac
155}
156
157# template function for author/owner
158author() {
159 if [ -z "$__AUTHOR" ]; then
160 __AUTHOR="$(git config --get user.name)" # try from git
161 [ -z "$__AUTHOR" ] && __AUTHOR="$(
162 getent passwd "$USER" | awk -F: '{sub(/,+/,"",$5);print $5}'
163 )" # or, try from getent
164 [ -z "$__AUTHOR" ] && __AUTHOR="$USER" # give up, get $USER
165 fi
166 put "$__AUTHOR"
167}
168
169email() {
170 if [ -z "$__EMAIL" ]; then
171 __EMAIL="$(git config --get user.email)" # try from git
172 fi
173 [ -n "$__EMAIL" ] && put "<$__EMAIL>"
174}
175
176# helpers
177put() { printf '%s\n' "$*"; }
178log() { $_quiet || put "$PRGN: $*" >&2; }
179
180# run
181$EXEC && licenser "$@"
diff --git a/licensor b/licensor new file mode 100755 index 0000000..47da938 --- /dev/null +++ b/licensor
@@ -0,0 +1,251 @@
1#!/bin/sh
2
3# Constants
4PRGN="${0##*/}"
5LICENSOR_CACHE="${XDG_CACHE_HOME:-$HOME/.cache/licensor"
6# Configuration
7: "${LICENSE_REPO_VERSION:=3.17}"
8: "${LICENSE_REPO_URL:=https://github.com/spdx/license-list-data/archive/refs/tags/v$LICENSE_REPO_VERSION.tar.gz}"
9: "${LICENSE_REPO_PATH:=license-list-data-$LICENSE_REPO_VERSION/template}"
10: "${LICENSOR_LICENSE:=MIT}"
11: "${LICENSOR_OUTPUT_FILE:=COPYING}"
12
13usage() {
14 cat <<EOF
15$PRGN: drop a lil ol license in yr project
16USAGE: $PRGN [-h|-m|-M]
17 $PRGN [FLAGS] [OPTIONS] [LICENSE]
18
19FLAGS:
20 -h Display this help and exit.
21 -l List available licenses and exit.
22 -L List available licenses, disregarding cache.
23 This flag will re-download the license repo.
24 -f Overwrite existing license.
25 -q Be quiet (don't log anything).
26
27OPTIONS:
28 -y YEARS Set copyright date(s) to YEARS.
29 Default: \$(date +%Y).
30 -a AUTHORS Set copyright holder(s) to AUTHOR.
31 Default: use the first of
32 - git config --get user.name
33 - getent password \$USER
34 - \$USER
35 -e EMAILS Set AUTHOR's EMAIL address.
36 Default: \$(git config --get user.email),
37 or stay blank.
38 -o FILE Output the fetched license to FILE.
39 Default: \$PWD/$LICENSOR_OUTPUT_FILE.
40
41PARAMETERS:
42 LICENSE The license to use.
43 Default: $LICENSOR_LICENSE.
44EOF
45 exit ${1:-0}
46}
47
48main() {
49 _force=false
50 _quiet=false
51 _fold=1
52 _optional=0
53 __width=70
54 __output="$LICENSOR_OUTPUT_FILE"
55 __year="$(date +%Y)"
56 __author="$(guess_author)"
57 __email="$(guess_email)"
58 __copyright="Copyright (C) $__year $__author <$__email>"
59
60 while getopts hlLs:fzZpPqy:a:e:o:w:c: opt; do
61 case "$opt" in
62 # commands
63 h) usage ;;
64 l) list_licenses && exit || exit $? ;;
65 L) list_licenses -f && exit || exit $? ;;
66 s) search_licenses "$OPTARG" ;;
67 # flags
68 f) _force=true ;;
69 z) _fold=1 ;;
70 Z) _fold=0 ;;
71 p) _optional=1 ;;
72 P) _optional=0 ;;
73 q) _quiet=true ;;
74 # options
75 y) __year="$OPTARG" ;;
76 a) __author="$OPTARG" ;;
77 e) __email="$OPTARG" ;;
78 o) __output="$OPTARG" ;;
79 w) __width="$OPTARG" ;;
80 c) __copyright="$OPTARG" ;;
81 *) usage 1 ;;
82 esac
83 done
84 shift $((OPTIND - 1))
85 __license="${1:-$LICENSOR_LICENSE}"
86
87 if [ -e "$__output" ] && ! $_force; then
88 log "File exists: $__output"
89 exit 3
90 fi
91
92 if [ "x$__output" = x- ]; then
93 __output=/dev/stdout
94 fi
95
96 license_file="$(get_license "$__license")" || exit $?
97 license_convert <"$LICENSOR_CACHE/$license_file.template.txt" \
98 "$__copyright" "$_optional" "$_fold" "$__width" >"$__output"
99 [ "$__output" != /dev/stdout ] && log "$__license license written to $__output."
100}
101
102get_licenses() {
103 # Get licenses from cache, or download them
104 if ! [ -d "$LICENSOR_CACHE" ] || [ "x$1" = "x-f" ]; then
105 log "Downlading licenses from $LICENSE_REPO_URL..."
106 mkdir -p "$LICENSOR_CACHE"
107 tmpfile="/tmp/licenses.tar.gz"
108 if ! [ -f "$tmpfile" ]; then
109 curl -o "$tmpfile" -L "$LICENSE_REPO_URL" >/dev/null 2>&1 ||
110 return 1
111 fi
112 log "Extracting licenses to $LICENSOR_CACHE..."
113 if tar -C "$LICENSOR_CACHE" \
114 -xvf "$tmpfile" --strip-components=2 \
115 "$LICENSE_REPO_PATH" >/dev/null 2>&1; then
116 rm "$tmpfile"
117 else
118 return 1
119 fi
120 fi
121}
122
123get_license() {
124 list_licenses | grep -iE '^'"$1"'$' || {
125 log "Can't find license \"$1\"."
126 exit 1
127 }
128}
129
130list_licenses() {
131 get_licenses "$1" || exit 1
132
133 find "$LICENSOR_CACHE" -iname '*.template.txt' |
134 sort |
135 xargs basename -s .template.txt
136}
137
138search_licenses() {
139 list_licenses | grep -iE "$1"
140 exit $?
141}
142
143guess_author() {
144 author="$(git config --get user.name)"
145 [ -z "$author" ] &&
146 author="$(getent passwd "$USER" | awk -F: '{sub(/,+/,"",$5);print $5}')"
147 [ -z "$author" ] &&
148 author="$USER"
149 put "$author"
150}
151guess_email() {
152 email="$(git config --get user.email)"
153 put "$email"
154}
155
156put() { printf '%s\n' "$*"; }
157log() { $_quiet || put "$PRGN: $*" >&2; }
158
159license_convert() {
160 copyright="$1" # "Copyright (C) 2022 Case Duckworth <acdw@acdw.net>"
161 show_optional="${2:-0}" # 0
162 fold_output="${3:-1}" # 1
163 fold_width="${4:-70}" # 70
164 awk '
165BEGIN {
166 foldOutput = '"$fold_output"'
167 foldWidth = '"$fold_width"'
168 showOptional = '"$show_optional"'
169 copyright = "'"$copyright"'"
170}
171{ buf = buf "\n" $0 }
172END {
173 split(buf, b, "")
174 c = 1
175 out = ""
176 optstr = ""
177 opt = 0
178 while (c <= length(b)) {
179 if (b[c] == "<" && b[c + 1] == "<") {
180 tok = ""
181 c += 2
182 closed = 0
183 while (! closed) {
184 tok = tok b[c++]
185 if (b[c] == ">" && b[c + 1] == ">") {
186 closed++
187 c += 2
188 }
189 }
190 if (tok ~ /^beginOptional/) {
191 opt = 1
192 } else if (tok == "endOptional") {
193 if (showOptional) {
194 out = out optstr
195 }
196 opt = 0
197 optstr = ""
198 } else if (tok ~ /^var/) {
199 split(tok, ta, ";")
200 name = ""
201 original = ""
202 for (a in ta) {
203 if (ta[a] ~ "^name") {
204 match(ta[a], /=".*/)
205 name = substr(ta[a], RSTART + 2, RLENGTH - 3)
206 } else if (ta[a] ~ "^original") {
207 match(ta[a], /=".*/)
208 original = substr(ta[a], RSTART + 2, RLENGTH - 3)
209 } else if (ta[a] ~ "^match") {
210 # currently not used
211 }
212 }
213 if (name == "copyright") {
214 out = out copyright
215 } else {
216 out = out original
217 }
218 }
219 continue
220 }
221 if (opt) {
222 optstr = optstr b[c++]
223 } else {
224 out = out b[c++]
225 }
226 }
227 # "Fold" the output
228 if (foldOutput) {
229 split(out, oa, "\n")
230 out = ""
231 for (l in oa) {
232 split(oa[l], la, FS)
233 lc = 0
234 for (w in la) {
235 lc += length(la[w]) + 1
236 if (lc >= foldWidth) {
237 out = out "\n" la[w] " "
238 lc = length(la[w]) + 1
239 } else {
240 out = out la[w] " "
241 }
242 }
243 out = out "\n"
244 }
245 }
246 print out
247}
248'
249}
250
251main "$@"