/[osn-commons]/trunk/srcproc/addlicense
ViewVC logotype

Annotation of /trunk/srcproc/addlicense

Parent Directory Parent Directory | Revision Log Revision Log


Revision 60 - (hide annotations)
Tue Sep 10 14:47:23 2024 UTC (6 months, 3 weeks ago) by rakinar2
File size: 11298 byte(s)
feat: add addlicense script

1 rakinar2 60 #!/bin/sh
2     #
3     # addlicense -- a script to insert license comments automatically
4     #
5     # This script is part of OSN Commons. Copyright (C) 2024 OSN Developers.
6     #
7     # OSN Commons is free software: you can redistribute it and/or modify it
8     # under the terms of the GNU General Public License as published by
9     # the Free Software Foundation, either version 3 of the License, or
10     # (at your option) any later version.
11     #
12     # OSN Commons is distributed in the hope that it will be useful,
13     # but WITHOUT ANY WARRANTY; without even the implied warranty of
14     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     # GNU General Public License for more details.
16     #
17     # You should have received a copy of the GNU General Public License
18     # along with OSN Commons. If not, see <https://www.gnu.org/licenses/>.
19     #
20    
21     me=$0
22     canonical_name=$(echo $me | rev | cut -d'/' -f1 | rev)
23    
24     if [ $(echo $me | cut -c1) = "/" ]; then
25     me=$canonical_name
26     fi
27    
28     version="1.0.0"
29    
30     usage() {
31     echo "Usage: $me [options...] [[directory...] | [-]]"
32     echo "Automatically insert license comments to the project's "
33     echo "source files."
34     echo ""
35     echo "Options:"
36     echo " -e, --exclude Add an exclusion pattern"
37     echo " -i, --include Add an inclusion pattern"
38     echo " -E, --exclude-file Exclude a file path"
39     echo " -I, --include-file Include a file path"
40     echo " -h, --help Show this help and exit"
41     echo " -v, --version Show version info and exit"
42     echo " -f, --file Specify a file containing the license"
43     echo " notice to insert"
44     echo ""
45     echo "Bug reports and general questions should be sent to "
46     echo "<[email protected]>."
47     exit 0
48     }
49    
50     show_version() {
51     echo "$canonical_name (OSN Commons) v$version"
52     echo ""
53     echo "Copyright (C) 2024 OSN Developers."
54     echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>."
55     echo "This is free software: you are free to change and redistribute it."
56     echo "There is NO WARRANTY, to the extent permitted by law."
57     echo ""
58     echo "Written by Ar Rakin."
59     exit 0
60     }
61    
62     trim_string() {
63     echo "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
64     }
65    
66     targets=""
67     exclpats=""
68     inclpats=""
69     exclfiles=""
70     inclfiles=""
71     license_notice_file=""
72     license_notice="/*
73     * This program is free software: you can redistribute it and/or modify
74     * it under the terms of the GNU General Public License as published by
75     * the Free Software Foundation, either version 3 of the License, or
76     * (at your option) any later version.
77     *
78     * This program is distributed in the hope that it will be useful,
79     * but WITHOUT ANY WARRANTY; without even the implied warranty of
80     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81     * GNU General Public License for more details.
82     *
83     * You should have received a copy of the GNU General Public License
84     * along with this program. If not, see <https://www.gnu.org/licenses/>.
85     */"
86     stdin_read=""
87    
88     while [ $# -gt 0 ]; do
89     case "$1" in
90     -h | --help)
91     usage
92     ;;
93    
94     -v | --version)
95     show_version
96     ;;
97    
98     -e | --exclude)
99     if [ -z "$2" ]; then
100     echo "$me: option requires an argument -- '$1'" >&2
101     echo "Try '$me --help' for more detailed information." >&2
102     exit 2
103     fi
104    
105     if [ "$2" != "$(echo "$2" | tr -d ':')" ]; then
106     echo "$me: exclusion patterns must not contain colons (':')" >&2
107     exit 2
108     fi
109    
110     if [ -z "$exclpats" ]; then
111     exclpats="$2"
112     else
113     exclpats="$exclpats:$2"
114     fi
115    
116     shift
117     ;;
118    
119     -i | --include)
120     if [ -z "$2" ]; then
121     echo "$me: option requires an argument -- '$1'" >&2
122     echo "Try '$me --help' for more detailed information." >&2
123     exit 2
124     fi
125    
126     if [ "$2" != "$(echo "$2" | tr -d ':')" ]; then
127     echo "$me: inclusion patterns must not contain colons (':')" >&2
128     exit 2
129     fi
130    
131     if [ -z "$inclpats" ]; then
132     inclpats="$2"
133     else
134     inclpats="$inclpats:$2"
135     fi
136    
137     shift
138     ;;
139    
140     -E | --exclude-file)
141     if [ -z "$2" ]; then
142     echo "$me: option requires an argument -- '$1'" >&2
143     echo "Try '$me --help' for more detailed information." >&2
144     exit 2
145     fi
146    
147     if [ "$2" != "$(echo "$2" | tr -d ':')" ]; then
148     echo "$me: file paths must not contain colons (':')" >&2
149     exit 2
150     fi
151    
152     if [ ! -f "$2" ]; then
153     echo "$me: $2: No such file or directory" >&2
154     exit 2
155     fi
156    
157     file=$(readlink -f "$2")
158    
159     if [ $? -ne 0 ]; then
160     echo "$me: $2: Ignoring" >&2
161     else
162     if [ -z "$exclfiles" ]; then
163     exclfiles="$file"
164     else
165     exclfiles="$exclfiles:$file"
166     fi
167     fi
168    
169     shift
170     ;;
171    
172     -I | --include-file)
173     if [ -z "$2" ]; then
174     echo "$me: option requires an argument -- '$1'" >&2
175     echo "Try '$me --help' for more detailed information." >&2
176     exit 2
177     fi
178    
179     if [ "$2" != "$(echo "$2" | tr -d ':')" ]; then
180     echo "$me: file paths must not contain colons (':')" >&2
181     exit 2
182     fi
183    
184     if [ ! -f "$2" ]; then
185     echo "$me: $2: No such file or directory" >&2
186     exit 2
187     fi
188    
189     file=$(readlink -f "$2")
190    
191     if [ $? -ne 0 ]; then
192     echo "$me: $2: Ignoring" >&2
193     else
194     if [ -z "$inclfiles" ]; then
195     inclfiles="$file"
196     else
197     inclfiles="$inclfiles:$file"
198     fi
199     fi
200    
201     shift
202     ;;
203    
204     -f | --file)
205     if [ -z "$2" ]; then
206     echo "$me: option requires an argument -- '$1'" >&2
207     echo "Try '$me --help' for more detailed information." >&2
208     exit 2
209     fi
210    
211     if [ "$2" = "-" ]; then
212     if [ -t 0 ]; then
213     echo "$me: nothing to read from standard input" >&2
214     exit 2
215     fi
216    
217     if [ ! -z "$stdin_read" ] && [ "$stdin_read" != "notice" ]; then
218     echo "$me: multiple options are being directed to standard input" >&2
219     exit 2
220     fi
221    
222     license_notice="$(cat)"
223     stdin_read="notice"
224     else
225     if [ ! -f "$2" ]; then
226     echo "$me: $2: No such file or directory" >&2
227     exit 2
228     fi
229    
230     license_notice_file="$2"
231     license_notice=$(cat $2)
232     fi
233    
234     shift
235     ;;
236    
237     -)
238     if [ -t 0 ]; then
239     echo "$me: nothing to read from standard input" >&2
240     exit 2
241     fi
242    
243     if [ ! -z "$stdin_read" ] && [ "$stdin_read" != "targets" ]; then
244     echo "$me: multiple options are being directed to standard input" >&2
245     exit 2
246     fi
247    
248     while IFS='' read -r line; do
249     if [ "$line" != "$(echo "$line" | tr -d ':')" ] || [ -z "$line" ]; then
250     echo "$me: target paths must not contain colons (':')" >&2
251     exit 2
252     fi
253    
254     if [ -z "$targets" ]; then
255     targets="$line"
256     else
257     targets="$targets:$line"
258     fi
259     done
260    
261     stdin_read="targets"
262     ;;
263    
264     -*)
265     echo "$me: Invalid option -- '$1'" >&2
266     echo "Try '$me --help' for more detailed information." >&2
267     exit 2
268     ;;
269    
270     *)
271     if [ "$1" != "$(echo "$1" | tr -d ':')" ] || [ -z "$1" ]; then
272     echo "$me: target paths must not contain colons (':')" >&2
273     exit 2
274     fi
275    
276     if [ -z "$targets" ]; then
277     targets="$1"
278     else
279     targets="$targets:$1"
280     fi
281     ;;
282     esac
283    
284     shift
285     done
286    
287     if [ -z "$targets" ]; then
288     echo "$me: No target operands specified" >&2
289     echo "Try '$me --help' for more detailed information" >&2
290     exit 2
291     fi
292    
293     success=0
294    
295     insert_license() {
296     set -e
297     local file=$1
298     local tmpfile=$(mktemp)
299    
300     echo "$license_notice" >$tmpfile
301     echo "" >>$tmpfile
302     cat $file >>$tmpfile
303     mv $tmpfile $file
304     set +e
305     }
306    
307     process_files() {
308     echo "$targets" | while IFS=':' read -r target; do
309     local stat_out=$(stat "$target" 2>&1)
310    
311     if [ $? -ne 0 ]; then
312     echo "$me: $(echo $stat_out | cut -c 7-)" >&2
313     continue
314     fi
315    
316     echo "$me: scanning: $target"
317     local find_cmd="find '$target' -type f ! -path \"*/*~\" \
318     ! -path \"*/.git/*\" ! -path \"*/.svn/*\" \
319     ! -path \"*/.hg/*\" ! -path \"*/CVS/*\" \
320     ! -path \"*/.bzr/*\" ! -path \"$me\""
321    
322     if [ ! -z "$exclpats" ]; then
323     local ifs="$IFS"
324    
325     IFS=":"
326    
327     for exclpat in $exclpats; do
328     find_cmd="$find_cmd ! -path \"$exclpat\""
329     done
330    
331     IFS="$ifs"
332     fi
333    
334     if [ ! -z "$inclpats" ]; then
335     local ifs="$IFS"
336    
337     IFS=":"
338    
339     for inclpat in $inclpats; do
340     find_cmd="$find_cmd -path \"$inclpat\""
341     done
342    
343     IFS="$ifs"
344     fi
345    
346     local files=$(eval $find_cmd)
347    
348     if [ -z "$files" ]; then
349     echo "$me: no files found" >&2
350     continue
351     fi
352    
353     local r_license_notice_file
354    
355     if [ ! -z "$license_notice_file" ]; then
356     r_license_notice_file=$(readlink -f "$license_notice_file")
357     fi
358    
359     for file in $files; do
360     local rpath=$(readlink -f "$file")
361    
362     if [ ! -z "$license_notice_file" ] && [ "$rpath" = "$r_license_notice_file" ]; then
363     continue
364     fi
365    
366     if [ ! -z "$exclfiles" ]; then
367     local ifs="$IFS"
368    
369     IFS=":"
370    
371     for exclfile in $exclfiles; do
372     if [ "$rpath" = "$exclfile" ]; then
373     continue 2
374     fi
375     done
376    
377     IFS="$ifs"
378     fi
379    
380     if [ ! -z "$inclfiles" ]; then
381     local ifs="$IFS"
382    
383     IFS=":"
384    
385     for inclfile in $inclfiles; do
386     if [ "$rpath" = "$inclfile" ]; then
387     break
388     fi
389     done
390    
391     if [ "$rpath" != "$inclfile" ]; then
392     continue
393     fi
394    
395     IFS="$ifs"
396     fi
397    
398     if file "$file" | grep -Eq 'binary|ELF|executable|data'; then
399     echo "$me: skipping binary file: $file"
400     continue
401     fi
402    
403     local license_notice_size=$(echo "$license_notice" | wc -c)
404     local part=$(sed ':a; /^$/d; $!{N; ba}; s/^[[:space:]]*//' $file | head -c $license_notice_size)
405    
406     if [ "$license_notice" = "$part" ]; then
407     echo "$me: license notice already present in: $file"
408     success=1
409     continue
410     fi
411    
412     echo "$me: inserting license comment to: $file"
413     insert_license $file
414     done
415    
416     success=1
417     done
418     }
419    
420     process_files
421    
422     if [ $success -ne 1 ]; then
423     exit 1
424     fi

Properties

Name Value
svn:executable *

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26