Browse Source

Update MKit to v0.0.24

Alois Mahdal 7 years ago
parent
commit
b783a7e838

+ 48
- 36
utils/mkit/include/build.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2
 
4
 
3
-. "$MKIT_DIR/include/ini.sh"   || die "cannot import ini.sh"
4
-. "$MKIT_DIR/include/facts.sh" || die "cannot import facts.sh"
5
+mkit_import ini
6
+mkit_import facts
5
 
7
 
6
 
8
 
7
 _build1() {
9
 _build1() {
8
     #
10
     #
9
-    # Process one skeleton
11
+    # Process one skeleton $1 of type $3 (or guessed) to path $2
10
     #
12
     #
11
-    local srcpath="$1"
12
-    local dstpath="$2"
13
-    local ftype="$3"
13
+    local srcpath=$1    # skeleton path
14
+    local dstpath=$2    # destination meaty animal path
15
+    local ftype=$3      # file/builder type
14
     test -n "$dstpath"  || dstpath=${srcpath%.skel}
16
     test -n "$dstpath"  || dstpath=${srcpath%.skel}
15
     test -n "$ftype"    || ftype=$(_guess_ftype "$dstpath")
17
     test -n "$ftype"    || ftype=$(_guess_ftype "$dstpath")
16
     debug_var srcpath dstpath ftype
18
     debug_var srcpath dstpath ftype
21
 
23
 
22
 _build1_ftype() {
24
 _build1_ftype() {
23
     #
25
     #
24
-    # Build a file of type $1
26
+    # Build a file of type $1; fom stdin to stdout
25
     #
27
     #
26
-    local ftype="$1"
28
+    local ftype=$1      # file/builder type
27
     case $ftype in
29
     case $ftype in
28
         MKIT_COMMON)    _expand_tokens "tokens" ;;
30
         MKIT_COMMON)    _expand_tokens "tokens" ;;
29
         markdown)       _expand_includes | _expand_tokens "tokens" ;;
31
         markdown)       _expand_includes | _expand_tokens "tokens" ;;
30
         rpmstuff)       _expand_tokens "tokens" "rpmstuff:tokens" ;;
32
         rpmstuff)       _expand_tokens "tokens" "rpmstuff:tokens" ;;
33
+        debstuff)       _expand_tokens "tokens" "debstuff:tokens" ;;
31
         *)              die "unknown file type: $ftype" ;;
34
         *)              die "unknown file type: $ftype" ;;
32
     esac
35
     esac
33
 }
36
 }
59
 
62
 
60
 _expand_tokens() {
63
 _expand_tokens() {
61
     #
64
     #
62
-    # Expand tokens from sections $@
65
+    # Read stdin, expanding tokens from sections $@
63
     #
66
     #
64
-    local script=$(mktemp --tmpdir mkit-tmp.XXXXXXXXXX)
65
-    local section varname varvalue
67
+    local script        # sed script cache
68
+    local section       # each section to expand tokens from
69
+    local varname       # each token name
70
+    local varvalue      # each token value
71
+    script=$(mktemp --tmpdir mkit-tmp.XXXXXXXXXX)
66
     {
72
     {
67
-        for section in "$@";
68
-        do
73
+        for section in "$@"; do
69
             debug_var section
74
             debug_var section
70
             ini lskeys "$section" \
75
             ini lskeys "$section" \
71
-              | while read varname;
72
-                do
76
+              | while read -r varname; do
73
                     varvalue="$(ini 1value "$section:$varname" | _qfs )"
77
                     varvalue="$(ini 1value "$section:$varname" | _qfs )"
74
                     echo "s|$varname|$varvalue|g;"
78
                     echo "s|$varname|$varvalue|g;"
75
                     debug_var varname varvalue
79
                     debug_var varname varvalue
77
         done
81
         done
78
         echo "s|__MKIT_PROJ_NAME__|$(ini 1value project:name | _qfs)|g;"
82
         echo "s|__MKIT_PROJ_NAME__|$(ini 1value project:name | _qfs)|g;"
79
         echo "s|__MKIT_PROJ_CODENAME__|$(ini 1value project:codename | _qfs)|g;"
83
         echo "s|__MKIT_PROJ_CODENAME__|$(ini 1value project:codename | _qfs)|g;"
84
+        echo "s|__MKIT_PROJ_LICENSE__|$(ini 1value project:license | _qfs)|g;"
80
         echo "s|__MKIT_PROJ_PKGNAME__|$(ini 1value project:pkgname | _qfs)|g;"
85
         echo "s|__MKIT_PROJ_PKGNAME__|$(ini 1value project:pkgname | _qfs)|g;"
81
         echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | _qfs)|g;"
86
         echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | _qfs)|g;"
82
         echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | _qfs)|g;"
87
         echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | _qfs)|g;"
93
     #
98
     #
94
     # Guess file type from destination path $1
99
     # Guess file type from destination path $1
95
     #
100
     #
96
-    local dstpath="$1"
101
+    local dstpath=$1    # destination path
97
     case $dstpath in
102
     case $dstpath in
98
         *.md) echo markdown    ;;
103
         *.md) echo markdown    ;;
99
         *)    echo MKIT_COMMON ;;
104
         *)    echo MKIT_COMMON ;;
114
     #
119
     #
115
     # Add meat to all skeletons
120
     # Add meat to all skeletons
116
     #
121
     #
117
-    local srcpath
122
+    local srcpath   # each source path
118
     find -type f -name '*.skel' \
123
     find -type f -name '*.skel' \
119
-     | while read srcpath;
120
-       do
124
+     | while read -r srcpath; do
121
            _build1 "$srcpath"
125
            _build1 "$srcpath"
122
        done
126
        done
123
 }
127
 }
124
 
128
 
125
 build_manpages() {
129
 build_manpages() {
126
-    local manfile mdfile
127
-    if command -v ronn >/dev/null;
128
-    then
130
+    #
131
+    # Build manpages using ronn
132
+    #
133
+    local manfile   # each manual file listed in '[files:man]'
134
+    local mdfile    # each source markdown file
135
+    if command -v ronn >/dev/null; then
129
         ini lskeys "files:man" \
136
         ini lskeys "files:man" \
130
-          | while read manfile;
131
-            do
137
+          | while read -r manfile; do
132
                 mdfile="$manfile.md"
138
                 mdfile="$manfile.md"
133
                 ronn -r "$mdfile"
139
                 ronn -r "$mdfile"
134
                 mkdir -p "$MKIT_LOCAL"
140
                 mkdir -p "$MKIT_LOCAL"
157
     #
163
     #
158
     # Build Debian stuff (eamed tarball, debian dir)
164
     # Build Debian stuff (eamed tarball, debian dir)
159
     #
165
     #
160
-    local version="$(semver)"
166
+    local version       # package version
167
+    local debian_skel   # 'debian' folder skeleton
168
+    local dfsrc         # each source file from ^^
169
+    local dftgt         # each built packaging file
170
+    version=$(semver)
161
 
171
 
162
     # tarball - we should already have by means of 'dist'
172
     # tarball - we should already have by means of 'dist'
163
     #
173
     #
168
 
178
 
169
     # read content of each mandatory file from debian_skel
179
     # read content of each mandatory file from debian_skel
170
     #
180
     #
171
-    local debian_skel=$(ini 1value dist:debstuff)
181
+    debian_skel=$(ini 1value dist:debstuff)
172
     test -n "$debian_skel" || die "dist:debstuff not specified"
182
     test -n "$debian_skel" || die "dist:debstuff not specified"
173
     test -d "$debian_skel" || die "debian directory template found: $debian_skel"
183
     test -d "$debian_skel" || die "debian directory template found: $debian_skel"
174
     mkdir -p debian/source
184
     mkdir -p debian/source
175
-    local dfsrc dftgt
176
     find "$debian_skel" -type f \
185
     find "$debian_skel" -type f \
177
-      | while read dfsrc;
178
-        do
186
+      | while read -r dfsrc; do
179
             dftgt="debian/${dfsrc#$debian_skel}"
187
             dftgt="debian/${dfsrc#$debian_skel}"
180
             mkdir -p "$(dirname "$dftgt")"
188
             mkdir -p "$(dirname "$dftgt")"
181
-            _build1 "$dfsrc" "$dftgt"
189
+            _build1 "$dfsrc" "$dftgt" debstuff
182
         done
190
         done
183
     echo debian >> "$MKIT_LOCAL/built.lst"
191
     echo debian >> "$MKIT_LOCAL/built.lst"
184
 }
192
 }
190
     #FIXME: lacking Makefile skills, we do this step twice fot
198
     #FIXME: lacking Makefile skills, we do this step twice fot
191
     #       rpmstuff, hence -f hack for gzip
199
     #       rpmstuff, hence -f hack for gzip
192
     #
200
     #
193
-    local version=$(semver)
194
-    local git_lasthash=$(git_lasthash)
195
-    local dirname=$MKIT_PROJ_PKGNAME-$version
201
+    local version           # tarball version
202
+    local git_lasthash      # last git commit hash
203
+    local dirname           # directory and tarball name
204
+    version=$(semver)
205
+    dirname=$MKIT_PROJ_PKGNAME-$version
206
+    git_lasthash=$(git_lasthash)
196
     mkdir -p "$dirname"
207
     mkdir -p "$dirname"
197
     ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
208
     ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
198
     update_version "$version" "$dirname/mkit.ini"
209
     update_version "$version" "$dirname/mkit.ini"
209
     #
220
     #
210
     # Build specfile
221
     # Build specfile
211
     #
222
     #
212
-    local specname="$MKIT_PROJ_PKGNAME.spec"
213
-    local specsrc="$(ini 1value "dist:rpmstuff")"
223
+    local specname=$MKIT_PROJ_PKGNAME.spec      # .spec filename
224
+    local specsrc                               # source of specfile
225
+    specsrc="$(ini 1value "dist:rpmstuff")"
214
     test -n "$specsrc" || die "dist:rpmstuff not specified"
226
     test -n "$specsrc" || die "dist:rpmstuff not specified"
215
     test -f "$specsrc" || die "specfile template not found: $specsrc"
227
     test -f "$specsrc" || die "specfile template not found: $specsrc"
216
-    _build1 "$specsrc" "$specname"
228
+    _build1 "$specsrc" "$specname" rpmstuff
217
 }
229
 }

+ 34
- 27
utils/mkit/include/deploy.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
4
+
5
+mkit_import ini
2
 
6
 
3
 _deploy_item() {
7
 _deploy_item() {
4
     #
8
     #
23
     # Directories are copied recursively, and mode is
27
     # Directories are copied recursively, and mode is
24
     # applied only to files.
28
     # applied only to files.
25
     #
29
     #
26
-    local src="$1"
27
-    local dst="$2"
28
-    local mode="${3:-$MKIT_DEFAULT_MODE}"
29
-    if test -d "$src";
30
-    then
31
-        _maybe mkdir -vp "$(dirname "$dst")"
32
-        _maybe cp -Tvr "$src" "$dst"
33
-        find "$dst" -type f \
34
-          | while read chmod_item;
35
-            do
36
-                _maybe chmod "$mode" "$chmod_item"
30
+    local src=$1                            # source path
31
+    local dst=$2                            # destination path
32
+    local mode=${3:-$MKIT_DEFAULT_MODE}     # mode
33
+    local item                              # each in directory
34
+    if test -d "$src"; then
35
+        find "$src" -type f \
36
+          | while read -r item; do
37
+                [[ $item =~ .skel$ ]] \
38
+                 && grep -q "${item%.skel}" "$MKIT_LOCAL/built.lst" \
39
+                 && continue
40
+                _deploy_item "$item" "$dst${item#$src}" "$mode"
37
             done
41
             done
38
     else
42
     else
39
         _maybe install -DTvm "$mode" "$src" "$dst"
43
         _maybe install -DTvm "$mode" "$src" "$dst"
44
     #
48
     #
45
     # Find out target path for src file $2 of group $1
49
     # Find out target path for src file $2 of group $1
46
     #
50
     #
47
-    local grp=$1
48
-    local src=$2
49
-    local dst=$3
51
+    local grp=$1        # deploy group
52
+    local src=$2        # each source
53
+    local dst=$3        # alternative destination name
50
     test -n "$dst" || dst=${src##*/}
54
     test -n "$dst" || dst=${src##*/}
51
     echo "$(_get_root "$grp")/$dst"
55
     echo "$(_get_root "$grp")/$dst"
52
 }
56
 }
55
     #
59
     #
56
     # Find out target root for group $1
60
     # Find out target root for group $1
57
     #
61
     #
58
-    local grp="$1"
59
-    local root=$(ini 1value "roots:$grp")
60
-    local destdir=$(ini 1value ENV:DESTDIR)
62
+    local grp=$1        # deploy group
63
+    local root          # root for this group
64
+    local destdir       # value of DESTDIR
65
+    root=$(ini 1value "roots:$grp")
66
+    destdir=$(ini 1value ENV:DESTDIR)
61
     destdir=${destdir%/}
67
     destdir=${destdir%/}
62
     case $destdir:$root in
68
     case $destdir:$root in
63
         *:)     die "missing in config.ini: roots:$grp" ;;
69
         *:)     die "missing in config.ini: roots:$grp" ;;
84
     #
90
     #
85
     # Install product
91
     # Install product
86
     #
92
     #
87
-    local dst group mode src
93
+    local group     # each deploy group
94
+    local mode      # mode (group-specific)
95
+    local src       # each source path
96
+    local dst       # each (final absolute) destination path
88
     ini lskeys "files" \
97
     ini lskeys "files" \
89
       | sort \
98
       | sort \
90
       | uniq \
99
       | uniq \
91
-      | while read group;
92
-        do
100
+      | while read -r group; do
93
             mode=$(ini 1value "modes:$group")
101
             mode=$(ini 1value "modes:$group")
94
             ini values "files:$group" \
102
             ini values "files:$group" \
95
-              | while read src dst;
96
-                do
103
+              | while read -r src dst; do
97
                     dst=$(_get_dst "$group" "$src" "$dst")
104
                     dst=$(_get_dst "$group" "$src" "$dst")
98
                     _deploy_item "$src" "$dst" "$mode"
105
                     _deploy_item "$src" "$dst" "$mode"
99
                 done
106
                 done
106
     #
113
     #
107
     # Uninstall product
114
     # Uninstall product
108
     #
115
     #
109
-    local dst group src
116
+    local group     # each deploy group
117
+    local src       # each source path
118
+    local dst       # each (final absolute) destination path
110
     ini lskeys "files" \
119
     ini lskeys "files" \
111
       | sort \
120
       | sort \
112
       | uniq \
121
       | uniq \
113
-      | while read group;
114
-        do
122
+      | while read -r group; do
115
             ini values "files:$group" \
123
             ini values "files:$group" \
116
-              | while read src dst;
117
-                do
124
+              | while read -r src dst; do
118
                     dst=$(_get_dst "$group" "$src" "$dst")
125
                     dst=$(_get_dst "$group" "$src" "$dst")
119
                     _maybe rm -vrf "$dst"
126
                     _maybe rm -vrf "$dst"
120
                 done
127
                 done

+ 21
- 14
utils/mkit/include/facts.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2
 
4
 
3
-. "$MKIT_DIR/include/ini.sh" || die "cannot import ini.sh"
5
+mkit_import ini
4
 
6
 
5
 git_bool() {
7
 git_bool() {
6
     #
8
     #
7
     # Get git bool (ie. exit status counts) $1
9
     # Get git bool (ie. exit status counts) $1
8
     #
10
     #
9
-    local bool_name="$1"
11
+    local bool_name=$1      # name of boolean to get
10
     git_present || warn "can't give bool outside git repo: $bool_name"
12
     git_present || warn "can't give bool outside git repo: $bool_name"
11
     case "$bool_name" in
13
     case "$bool_name" in
12
         dirty_files)
14
         dirty_files)
29
     #
31
     #
30
     # Get git fact $1
32
     # Get git fact $1
31
     #
33
     #
32
-    local fact_name="$1"
34
+    local fact_name=$1      # name of fact to get
33
     git_present || warn "can't give fact outside git repo: $fact_name"
35
     git_present || warn "can't give fact outside git repo: $fact_name"
34
     case "$fact_name" in
36
     case "$fact_name" in
35
         latest_tag)
37
         latest_tag)
88
     # work if you got outside the git repo in other way than dist
90
     # work if you got outside the git repo in other way than dist
89
     # target, but that's actually expected.)
91
     # target, but that's actually expected.)
90
     #
92
     #
91
-    if git_present;
92
-    then    # we are in git repo
93
-        local last_hash=$(git rev-parse HEAD)
93
+    local last_hash     # last commit hash
94
+    if git_present; then    # we are in git repo
95
+        last_hash=$(git rev-parse HEAD)
94
         echo -n "$last_hash"
96
         echo -n "$last_hash"
95
         git_bool dirty && echo -n ".dirty"
97
         git_bool dirty && echo -n ".dirty"
96
     else    # we are outside (eg. distributor's build dir')
98
     else    # we are outside (eg. distributor's build dir')
146
     # FIXME:  Using project:prerl for release IDs may not be compatible with
148
     # FIXME:  Using project:prerl for release IDs may not be compatible with
147
     #         release strategy implemented in release.sh
149
     #         release strategy implemented in release.sh
148
     #
150
     #
149
-    local version=$(ini 1value project:version)
150
-    local prerl=$(ini 1value project:prerl)
151
-    grep ":" <<<"$prerl" && warn "colon in project:prerl may corrupt version data: $prerl"
151
+    local version       # version string (final result)
152
+    local prerl         # pre-release keyword (from mkit.ini, eg. 'alpha')
153
+    local latest_tag    # latest git tag
154
+    local commit        # commit indicator (CURRENT_BRANCH.gHASH)
155
+    local dirty         # 0 if dirty, 1 if clean
156
+    local suffix        # version suffix
157
+    version=$(ini 1value project:version)
158
+    prerl=$(ini 1value project:prerl)
159
+    grep ":" <<<"$prerl" \
160
+     && warn "colon in project:prerl may corrupt version data: $prerl"
152
     if git_present;
161
     if git_present;
153
     then    # we are in git repo... so we can get smart
162
     then    # we are in git repo... so we can get smart
154
-        local latest_tag=$(git_fact latest_tag)
163
+        latest_tag=$(git_fact latest_tag)
155
         if ! git describe --tags --exact-match HEAD >&/dev/null;
164
         if ! git describe --tags --exact-match HEAD >&/dev/null;
156
         then    # we are at a later commit than the last tag
165
         then    # we are at a later commit than the last tag
157
-            local commit="$(git_fact current_branch).g$(git_fact latest_sha)"
166
+            commit="$(git_fact current_branch).g$(git_fact latest_sha)"
158
         fi
167
         fi
159
-        local dirty=""
160
-        local suffix=""
161
         git_bool dirty; dirty=$?
168
         git_bool dirty; dirty=$?
162
         test -n "$latest_tag" && version=${latest_tag:1}
169
         test -n "$latest_tag" && version=${latest_tag:1}
163
         case "$dirty:$commit" in
170
         case "$dirty:$commit" in
165
             0:)  suffix="+dirty"         ;;
172
             0:)  suffix="+dirty"         ;;
166
             1:*) suffix="+$commit"       ;;
173
             1:*) suffix="+$commit"       ;;
167
             0:*) suffix="+$commit.dirty" ;;
174
             0:*) suffix="+$commit.dirty" ;;
168
-            *)   suffix=MKIT_BUG;
175
+            *)   suffix=MKIT_BUG
169
                  warn "MKIT_BUG: bad dirt/commit detection" ;;
176
                  warn "MKIT_BUG: bad dirt/commit detection" ;;
170
         esac
177
         esac
171
         test -n "$prerl" && suffix="-$prerl$suffix"
178
         test -n "$prerl" && suffix="-$prerl$suffix"

+ 34
- 32
utils/mkit/include/ini.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2
 
4
 
3
 _ini_cat() {
5
 _ini_cat() {
4
     #
6
     #
5
     # A no-op for text stream
7
     # A no-op for text stream
6
     #
8
     #
7
-    while read line;
8
-    do
9
+    local line      # each line
10
+    while read -r line; do
9
         printf -- "%s\n" "$line"
11
         printf -- "%s\n" "$line"
10
     done
12
     done
11
 }
13
 }
14
     #
16
     #
15
     # Expand reference value (prefix only)
17
     # Expand reference value (prefix only)
16
     #
18
     #
17
-    local line suffix ref value
18
-    while read line;                        # [foo:bar]/path
19
-    do
19
+    local line      # each input line
20
+    local suffix    # tail of the line
21
+    local ref       # reference
22
+    local value     # value if reference
23
+    while read -r line; do                  # [foo:bar]/path
20
         suffix="${line#\[*\]}"              # /path
24
         suffix="${line#\[*\]}"              # /path
21
         ref="${line%$suffix}"               # [foo:bar]
25
         ref="${line%$suffix}"               # [foo:bar]
22
         ref="${ref%\]}"                     # [foo:bar
26
         ref="${ref%\]}"                     # [foo:bar
30
     #
34
     #
31
     # Read key from a section
35
     # Read key from a section
32
     #
36
     #
33
-    local wnt=$1
37
+    local wnt=$1    # wanted key
34
     grep '.' \
38
     grep '.' \
35
       | grep -v '\s*#' \
39
       | grep -v '\s*#' \
36
       | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
40
       | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
48
     #     [files:share]
52
     #     [files:share]
49
     #         my/lib.sh   = proj/my/lib.sh
53
     #         my/lib.sh   = proj/my/lib.sh
50
     #
54
     #
51
-    local wnt="$1"
52
-    local wntkey="${wnt##*:}"
53
-    local wntsec="${wnt%:$wntkey}"
54
-    if test "$wntsec" = 'ENV';
55
-    then
56
-        local override="${!wntkey}"
57
-        if test -n "$override";
58
-        then
59
-            echo "$override"
60
-            return
61
-        fi
55
+    local wnt=$1                    # wanted path
56
+    local wntkey=${wnt##*:}         # ^^ key part
57
+    local wntsec=${wnt%:$wntkey}    # ^^ section part
58
+    local override                  # ENV override (only ENV section)
59
+    if test "$wntsec" = 'ENV'; then
60
+        override=${!wntkey}
61
+        test -n "$override" \
62
+         && echo "$override" \
63
+         && return
62
     fi
64
     fi
63
     _ini_grepsec "$wntsec" | _ini_grepkey "$wntkey"
65
     _ini_grepsec "$wntsec" | _ini_grepkey "$wntkey"
64
 }
66
 }
67
     #
69
     #
68
     # Read one INI section
70
     # Read one INI section
69
     #
71
     #
70
-    local wnt="$1"
71
-    local ok=false
72
+    local wnt=$1        # wanted section name
73
+    local ok=false      # are we in the section?
74
+    local line          # each input line
72
     grep '.' \
75
     grep '.' \
73
       | grep -v '\s*#' \
76
       | grep -v '\s*#' \
74
-      | while read line;
75
-        do
77
+      | while read -r line; do
76
             case "$line" in
78
             case "$line" in
77
                 \[$wnt\]) ok=true;  continue ;;
79
                 \[$wnt\]) ok=true;  continue ;;
78
                 \[*\])    ok=false; continue ;;
80
                 \[*\])    ok=false; continue ;;
87
     #
89
     #
88
     # List keys from a section
90
     # List keys from a section
89
     #
91
     #
90
-    local sct="$1"
91
-    _ini_grepsec "$sct" | cut -d= -f1 | sort | uniq
92
+    local sct=$1    # section of interest
93
+    _ini_grepsec "$sct" | cut -d= -f1 | awk '!x[$0]++'
92
 }
94
 }
93
 
95
 
94
 _ini_maybe_expand() {
96
 _ini_maybe_expand() {
95
     #
97
     #
96
     # Decide whether or not to expand
98
     # Decide whether or not to expand
97
     #
99
     #
98
-    if test "$MKIT_INI_EXPAND" -gt 0;
99
-    then
100
+    if test "$MKIT_INI_EXPAND" -gt 0; then
100
         MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) _ini_expand
101
         MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) _ini_expand
101
     else
102
     else
102
         _ini_cat
103
         _ini_cat
107
     #
108
     #
108
     # do ini operation
109
     # do ini operation
109
     #
110
     #
110
-    local op=$1
111
-    local arg=$2
112
-    local fn
113
-    local limit=_ini_cat
111
+    local op=$1             # operator
112
+    local arg=$2            # argument
113
+    local fn                # internal function implementing $op
114
+    local limit=_ini_cat    # limiting internal function
114
     case $op in
115
     case $op in
115
         lskeys) fn=_ini_lskeys   ;;
116
         lskeys) fn=_ini_lskeys   ;;
116
         sec)    fn=_ini_grepsec  ;;
117
         sec)    fn=_ini_grepsec  ;;
125
     #
126
     #
126
     # Change project.version in mkit.ini at path $2 to version $1
127
     # Change project.version in mkit.ini at path $2 to version $1
127
     #
128
     #
128
-    local version="$1"
129
-    local inifile="$2"
130
-    local tmp=$(mktemp -t mkit.update_version.XXXXXXXX)
129
+    local version=$1    # new version
130
+    local inifile=$2    # mkit.ini path
131
+    local tmp           # mkit.ini cache
132
+    tmp=$(mktemp -t mkit.update_version.XXXXXXXX)
131
     <"$inifile" perl -e '
133
     <"$inifile" perl -e '
132
         my $hit = 0;
134
         my $hit = 0;
133
         my $done = 0;
135
         my $done = 0;

+ 42
- 22
utils/mkit/include/mkit.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2
 
4
 
3
-. "$MKIT_DIR/include/build.sh"  || die "cannot import build.sh"
4
-. "$MKIT_DIR/include/deploy.sh" || die "cannot import deploy.sh"
5
-. "$MKIT_DIR/include/release.sh" || die "cannot import release.sh"
6
-. "$MKIT_DIR/include/ini.sh"    || die "cannot import ini.sh"
5
+die() {
6
+    #
7
+    # Exit with message and non-zero exit status
8
+    #
9
+    echo "fatal: $*" >&2
10
+    exit 4
11
+}
12
+
13
+mkit_import() {
14
+    #
15
+    # Import mkit module $1.sh
16
+    #
17
+    # Check for module, source it and die with reasonable message if needed.
18
+    #
19
+    local modname=$1
20
+    local modpath
21
+    modpath="$MKIT_DIR/include/$modname.sh"
22
+    test -f "$modpath" || die "no such module: $modpath"
23
+    bash -n "$modpath" || die "bad syntax: $modpath"
24
+    #shellcheck disable=SC1090
25
+    . "$modpath" || die "failed to import: $modname"
26
+}
27
+
28
+mkit_import build
29
+mkit_import deploy
30
+mkit_import release
31
+mkit_import ini
7
 
32
 
8
 _valid_targets() {
33
 _valid_targets() {
9
     #
34
     #
15
     echo debstuff
40
     echo debstuff
16
     echo dist
41
     echo dist
17
     echo install
42
     echo install
43
+    echo release
18
     echo release_x
44
     echo release_x
19
     echo release_y
45
     echo release_y
20
     echo release_z
46
     echo release_z
21
     echo rpmstuff
47
     echo rpmstuff
22
     echo uninstall
48
     echo uninstall
49
+    echo vbump
23
     echo vbump_x
50
     echo vbump_x
24
     echo vbump_y
51
     echo vbump_y
25
     echo vbump_z
52
     echo vbump_z
38
     # Print debug message
65
     # Print debug message
39
     #
66
     #
40
     $MKIT_DEBUG || return 0
67
     $MKIT_DEBUG || return 0
41
-    local __mkit_debug_var_name__
42
-    for __mkit_debug_var_name__ in "$@";
43
-    do
68
+    local __mkit_debug_var_name__       # variable name to debug
69
+    for __mkit_debug_var_name__ in "$@"; do
44
         {
70
         {
45
             echo -n "MKIT_DEBUG: ${FUNCNAME[1]}():"
71
             echo -n "MKIT_DEBUG: ${FUNCNAME[1]}():"
46
             echo -n " $__mkit_debug_var_name__"
72
             echo -n " $__mkit_debug_var_name__"
50
     done
76
     done
51
 }
77
 }
52
 
78
 
53
-die() {
54
-    #
55
-    # Exit with message and non-zero exit status
56
-    #
57
-    echo "fatal: $*" >&2
58
-    exit 4
59
-}
60
-
61
 _compver() {
79
 _compver() {
62
     #
80
     #
63
     # True if version $1 matches our version
81
     # True if version $1 matches our version
65
     # If our x is 0, check first two fragments, otherwise check just
83
     # If our x is 0, check first two fragments, otherwise check just
66
     # the x.  Fragments must equal.
84
     # the x.  Fragments must equal.
67
     #
85
     #
68
-    local their_ver our_x our_y their_x their_y
69
-    their_ver="$1"
86
+    local their_ver=$1      # their version
87
+    local our_x             # our X
88
+    local our_y             # our Y
89
+    local their_x           # their X
90
+    local their_y           # their Y
70
     their_x=${their_ver%%.*}
91
     their_x=${their_ver%%.*}
71
     their_y=${their_ver##$their_x.}
92
     their_y=${their_ver##$their_x.}
72
     their_y=${their_y%%.*}
93
     their_y=${their_y%%.*}
89
     # Look for "#mkit version=0.0.0" or similar in first or last
110
     # Look for "#mkit version=0.0.0" or similar in first or last
90
     # 3 lines of the file; then check if the version is supported.
111
     # 3 lines of the file; then check if the version is supported.
91
     #
112
     #
92
-    local ver_line
93
-    local their_ver
113
+    local ver_line      # line declaring version
114
+    local their_ver     # the declared version
94
     ver_line=$(
115
     ver_line=$(
95
         {
116
         {
96
             head -3 "$MKIT_INI"
117
             head -3 "$MKIT_INI"
97
-            tac "$MKIT_INI" | tail -3
118
+            tail -3 "$MKIT_INI"
98
         } | grep -m 1 -E '^# *mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
119
         } | grep -m 1 -E '^# *mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
99
     )
120
     )
100
     test -n "$ver_line" \
121
     test -n "$ver_line" \
122
     #
143
     #
123
     # Call correct function based on $1
144
     # Call correct function based on $1
124
     #
145
     #
125
-    if _valid_targets | grep -qwx "^$1";
126
-    then
146
+    if _valid_targets | grep -qwx "^$1"; then
127
         "$1"
147
         "$1"
128
     else
148
     else
129
         {
149
         {

+ 72
- 24
utils/mkit/include/release.sh View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2
 
4
 
3
-. "$MKIT_DIR/include/ini.sh"   || die "cannot import ini.sh"
4
-. "$MKIT_DIR/include/facts.sh" || die "cannot import facts.sh"
5
+mkit_import ini
6
+mkit_import facts
5
 
7
 
6
 _bump_version() {
8
 _bump_version() {
7
     #
9
     #
8
     # Bump version on stdin by level $1 (x, y or z)
10
     # Bump version on stdin by level $1 (x, y or z)
9
     #
11
     #
10
-    local rlevel=$1
11
-    local old
12
+    local rlevel=$1     # release level
13
+    local old           # old version
14
+    local oldx          # ... X
15
+    local oldz          # ... Z
16
+    local oldy          # ... Y
17
+    local tmpy          # Y parsing cache
18
+    local new           # bumped version
12
     read -r old
19
     read -r old
13
-    local oldx=${old%.*.*}
14
-    local oldz=${old#*.*.}
15
-    local tmpy=${old%.*}
16
-    local oldy=${tmpy#*.}
17
-    local new=""
20
+    oldx=${old%.*.*}
21
+    oldz=${old#*.*.}
22
+    tmpy=${old%.*}
23
+    oldy=${tmpy#*.}
18
     case $rlevel in
24
     case $rlevel in
19
         x) new="$((oldx+MKIT_BUMPSIZE)).0.0"            ;;
25
         x) new="$((oldx+MKIT_BUMPSIZE)).0.0"            ;;
20
         y) new="$oldx.$((oldy+MKIT_BUMPSIZE)).0"        ;;
26
         y) new="$oldx.$((oldy+MKIT_BUMPSIZE)).0"        ;;
28
     #
34
     #
29
     # Die if blocking condition $1 is detected
35
     # Die if blocking condition $1 is detected
30
     #
36
     #
31
-    local condition="$1"
32
-    local x
37
+    local condition=$1      # condition name
38
+    local oracle            # expected value
33
     case "$condition" in
39
     case "$condition" in
34
         git_present)
40
         git_present)
35
             git rev-parse HEAD >&/dev/null\
41
             git rev-parse HEAD >&/dev/null\
36
              || die "cannot do this outside git repo"
42
              || die "cannot do this outside git repo"
37
             ;;
43
             ;;
38
         at_relsrc)
44
         at_relsrc)
39
-            local relsrc=$(ini 1value project:relsrc)
45
+            oracle=$(ini 1value project:relsrc)
40
             git_fact current_branch \
46
             git_fact current_branch \
41
-              | grep -qFx "$relsrc" \
42
-             || die "you are not on release source branch: $relsrc"
47
+              | grep -qFx "$oracle" \
48
+             || die "you are not on release source branch: $oracle"
43
             ;;
49
             ;;
44
         not_dirty)
50
         not_dirty)
45
             git diff --shortstat 2>/dev/null \
51
             git diff --shortstat 2>/dev/null \
46
               | grep -q . \
52
               | grep -q . \
47
-             && die "tree is dirty: $dirt"
53
+             && die "tree is dirty!"
48
             ;;
54
             ;;
49
         tags_ok)
55
         tags_ok)
50
             git_fact latest_tag \
56
             git_fact latest_tag \
62
              && die "WIP commit since $(git_fact latest_tag)"
68
              && die "WIP commit since $(git_fact latest_tag)"
63
             ;;
69
             ;;
64
         ini_version)
70
         ini_version)
65
-            local oracle=$(git_fact latest_version | _bump_version "$rlevel")
71
+            oracle=$(git_fact latest_version | _bump_version "$rlevel")
66
             ini 1value project:version  \
72
             ini 1value project:version  \
67
               | grep -qFx "$oracle" \
73
               | grep -qFx "$oracle" \
68
              || die "new version not in mkit.ini: $oracle"
74
              || die "new version not in mkit.ini: $oracle"
83
     # FIXME: Using project:prerl as build.sh:semver() does may not be
89
     # FIXME: Using project:prerl as build.sh:semver() does may not be
84
     #        compatible with this release strategy
90
     #        compatible with this release strategy
85
     #
91
     #
86
-    local rlevel=$1
87
-    local newtag
88
-    local reldst
92
+    local rlevel=$1     # release level (x, y or z)
93
+    local newtag        # new tag
94
+    local relsrc        # release source branch (if any)
95
+    local reldst        # release destination branch (if any)
89
 
96
 
90
     _relck git_present
97
     _relck git_present
91
     _relck at_relsrc
98
     _relck at_relsrc
101
     $MKIT_DRY && return
108
     $MKIT_DRY && return
102
     git tag -m "$(_release_msg)" "$newtag"
109
     git tag -m "$(_release_msg)" "$newtag"
103
 
110
 
111
+    relsrc=$(ini 1value project:relsrc)
104
     reldst=$(ini 1value project:reldst)
112
     reldst=$(ini 1value project:reldst)
105
-    debug_var reldst
106
-    if test -n "$reldst";
107
-    then
113
+    debug_var relsrc reldst
114
+    if test -n "$reldst" && test "$reldst" != "$relsrc"; then
108
         git branch -f "$reldst" "$newtag"
115
         git branch -f "$reldst" "$newtag"
109
     fi
116
     fi
110
 }
117
 }
127
 }
134
 }
128
 
135
 
129
 _vbump() {
136
 _vbump() {
130
-    local rlevel="$1"
131
-    local nextver   # after the bump
137
+    #
138
+    # Do version bump at level $1
139
+    #
140
+    # Perform checks, compute new version, update mkit.ini and initiate
141
+    # 'Bump version' commit with changelog template.
142
+    #
143
+    local rlevel=$1     # bump level (x, y or z)
144
+    local nextver       # version after the bump
132
     _relck git_present
145
     _relck git_present
133
     _relck at_relsrc
146
     _relck at_relsrc
134
     _relck not_dirty
147
     _relck not_dirty
143
 }
156
 }
144
 
157
 
145
 _vbump_gitmsg() {
158
 _vbump_gitmsg() {
159
+    #
160
+    # Compose git message template for 'Bump version' commit
161
+    #
146
     echo "Bump version"
162
     echo "Bump version"
147
     echo ""
163
     echo ""
148
     echo "Overview of changes:"
164
     echo "Overview of changes:"
155
         '
171
         '
156
 }
172
 }
157
 
173
 
174
+release() {
175
+    #
176
+    # Perform release on Z level
177
+    #
178
+    _release z
179
+}
180
+
158
 release_x() {
181
 release_x() {
182
+    #
183
+    # Perform release on X level
184
+    #
159
     _release x
185
     _release x
160
 }
186
 }
161
 
187
 
162
 release_y() {
188
 release_y() {
189
+    #
190
+    # Perform release on Y level
191
+    #
163
     _release y
192
     _release y
164
 }
193
 }
165
 
194
 
166
 release_z() {
195
 release_z() {
196
+    #
197
+    # Perform release on Z level
198
+    #
167
     _release z
199
     _release z
168
 }
200
 }
169
 
201
 
202
+vbump() {
203
+    #
204
+    # Perform version bump on Z level
205
+    #
206
+    _vbump z
207
+}
208
+
170
 vbump_x() {
209
 vbump_x() {
210
+    #
211
+    # Perform version bump on X level
212
+    #
171
     _vbump x
213
     _vbump x
172
 }
214
 }
173
 
215
 
174
 vbump_y() {
216
 vbump_y() {
217
+    #
218
+    # Perform version bump on Y level
219
+    #
175
     _vbump y
220
     _vbump y
176
 }
221
 }
177
 
222
 
178
 vbump_z() {
223
 vbump_z() {
224
+    #
225
+    # Perform version bump on Z level
226
+    #
179
     _vbump z
227
     _vbump z
180
 }
228
 }

+ 60
- 0
utils/mkit/include/vars.sh View File

1
+#!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
4
+
5
+
6
+#
7
+# Bump size (for vbump_? and release_?)
8
+#
9
+MKIT_BUMPSIZE=${MKIT_BUMPSIZE:-1}
10
+
11
+#
12
+# Debug mode (true|false)
13
+#
14
+MKIT_DEBUG=${MKIT_DEBUG:-false}
15
+
16
+#
17
+# Default deploy mode for files
18
+#
19
+MKIT_DEFAULT_MODE="644"
20
+
21
+#
22
+# Dry mode (true|false)
23
+#
24
+# Set to true to not install anything. Implies MKIT_DEBUG.
25
+#
26
+MKIT_DRY=${MKIT_DRY:-false}
27
+
28
+#
29
+# Path to mkit.ini
30
+#
31
+MKIT_INI=${MKIT_INI:-mkit.ini}
32
+
33
+#
34
+# Limit ini expansion depth
35
+#
36
+# To avoid endless loops, this value is subtracted each
37
+# time ini() expands a reference; when zero is reached,
38
+# no more expansions happen.
39
+#
40
+MKIT_INI_EXPAND=2
41
+
42
+#
43
+# Path to MKit local config and temp
44
+#
45
+# Typically hidden in project root, here MKit can
46
+# save its temporary lists.
47
+#
48
+MKIT_LOCAL=${MKIT_LOCAL:-.mkit}
49
+
50
+#
51
+# Package name
52
+#
53
+# Used as base for tarball and in some default tokens.
54
+#
55
+MKIT_PROJ_PKGNAME=""
56
+
57
+#
58
+# This MKit version
59
+#
60
+MKIT_VERSION=0.0.24

+ 15
- 63
utils/mkit/make View File

1
 #!/bin/bash
1
 #!/bin/bash
2
+#shellcheck disable=SC2034
2
 # mkit - simple install helper
3
 # mkit - simple install helper
3
 # See LICENSE file for copyright and license details.
4
 # See LICENSE file for copyright and license details.
4
 
5
 
5
-die() {
6
-    echo "$@" && exit 9
6
+init_core() {
7
+    #
8
+    # Load core module (or die)
9
+    #
10
+    #shellcheck disable=SC1090
11
+    . "$MKIT_DIR/include/mkit.sh" \
12
+     && . "$MKIT_DIR/include/vars.sh" \
13
+     && return 0
14
+    echo "failed to load core; check if MKIT_DIR is set properly: $MKIT_DIR" >&2
15
+    exit 9
7
 }
16
 }
8
 
17
 
9
-
10
-#
11
-# Bump size (for vbump_? and release_?)
12
-#
13
-MKIT_BUMPSIZE=${MKIT_BUMPSIZE:-1}
14
-
15
-#
16
-# Debug mode (true|false)
17
-#
18
-MKIT_DEBUG=${MKIT_DEBUG:-false}
19
-
20
-#
21
-# Default deploy mode for files
22
-#
23
-MKIT_DEFAULT_MODE="644"
24
-
25
 #
18
 #
26
 # Path to MKit dir (where 'include' is)
19
 # Path to MKit dir (where 'include' is)
27
 #
20
 #
28
 MKIT_DIR=${MKIT_DIR:-$(dirname "$0")}
21
 MKIT_DIR=${MKIT_DIR:-$(dirname "$0")}
29
 
22
 
30
-#
31
-# Dry mode (true|false)
32
-#
33
-# Set to true to not install anything. Implies MKIT_DEBUG.
34
-#
35
-MKIT_DRY=${MKIT_DRY:-false}
36
-
37
-#
38
-# Path to mkit.ini
39
-#
40
-MKIT_INI=${MKIT_INI:-mkit.ini}
41
-
42
-#
43
-# Limit ini expansion depth
44
-#
45
-# To avoid endless loops, this value is subtracted each
46
-# time ini() expands a reference; when zero is reached,
47
-# no more expansions happen.
48
-#
49
-MKIT_INI_EXPAND=2
50
-
51
-#
52
-# Path to MKit local config and temp
53
-#
54
-# Typically hidden in project root, here MKit can
55
-# save its temporary lists.
56
-#
57
-MKIT_LOCAL=${MKIT_LOCAL:-.mkit}
58
-
59
-#
60
-# Package name
61
-#
62
-# Used as base for tarball and in some default tokens.
63
-#
64
-MKIT_PROJ_PKGNAME=""
65
-
66
-#
67
-# This MKit version
68
-#
69
-MKIT_VERSION=0.0.18
70
-
71
 
23
 
72
-. "$MKIT_DIR/include/mkit.sh" || die "failed to init; check if MKIT_DIR is set properly: $MKIT_DIR"
24
+init_core
73
 
25
 
74
 case "$1" in
26
 case "$1" in
75
-    --version-semver) echo "$MKIT_VERSION"; exit 0 ;;
76
-    --version)        echo "Mkit (Simple Makefile target helper) $MKIT_VERSION"
77
-                      exit 0 ;;
27
+    -V|--version-semver)    echo "$MKIT_VERSION"; exit 0 ;;
28
+    --version)              echo "Mkit (Simple Makefile target helper) $MKIT_VERSION"
29
+                            exit 0 ;;
78
 esac
30
 esac
79
 
31
 
80
 mkit_init
32
 mkit_init

+ 7
- 1
utils/mkit/mkit.mk View File

26
 install: all
26
 install: all
27
 	@$(MKIT_DIR)/make install
27
 	@$(MKIT_DIR)/make install
28
 
28
 
29
+release:
30
+	@$(MKIT_DIR)/make release
31
+
29
 release_x:
32
 release_x:
30
 	@$(MKIT_DIR)/make release_x
33
 	@$(MKIT_DIR)/make release_x
31
 
34
 
38
 uninstall:
41
 uninstall:
39
 	@$(MKIT_DIR)/make uninstall
42
 	@$(MKIT_DIR)/make uninstall
40
 
43
 
44
+vbump:
45
+	@$(MKIT_DIR)/make vbump
46
+
41
 vbump_x:
47
 vbump_x:
42
 	@$(MKIT_DIR)/make vbump_x
48
 	@$(MKIT_DIR)/make vbump_x
43
 
49
 
47
 vbump_z:
53
 vbump_z:
48
 	@$(MKIT_DIR)/make vbump_z
54
 	@$(MKIT_DIR)/make vbump_z
49
 
55
 
50
-.PHONY: all clean dist rpmstuff install uninstall release_x release_y release_z vbump_x vbump_y vbump_z
56
+.PHONY: all clean dist rpmstuff install uninstall release release_x release_y release_z vbump vbump_x vbump_y vbump_z

+ 698
- 0
utils/mkit/stub View File

1
+#!/bin/bash
2
+# mkit - simple install helper
3
+# See LICENSE file for copyright and license details.
4
+
5
+init_core() {
6
+    #
7
+    # Load core modules (or die)
8
+    #
9
+    #shellcheck disable=SC1090
10
+    . "$MKIT_DIR/include/mkit.sh" \
11
+     && . "$MKIT_DIR/include/vars.sh" \
12
+     && return 0
13
+    echo "failed to load core; check if MKIT_DIR is set properly: $MKIT_DIR" >&2
14
+    exit 9
15
+}
16
+
17
+#
18
+# Path to MKit dir (where 'include' is)
19
+#
20
+MKIT_DIR=${MKIT_DIR:-$(dirname "$0")}
21
+
22
+init_core
23
+
24
+mkit_import ini
25
+
26
+declare -A MKIT_STUB_LICENSES
27
+MKIT_STUB_LICENSES[GPLv1]="http://www.gnu.org/licenses/old-licenses/gpl-1.0.md"
28
+MKIT_STUB_LICENSES[GPLv2]="http://www.gnu.org/licenses/old-licenses/gpl-2.0.md"
29
+MKIT_STUB_LICENSES[GPLv3]="http://www.gnu.org/licenses/gpl-3.0.md"
30
+MKIT_STUB_LICENSES[LGPLv2]="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.md"
31
+MKIT_STUB_LICENSES[LGPLv3]="http://www.gnu.org/licenses/lgpl-3.0.md"
32
+MKIT_STUB_LICENSES[AGPLv3]="http://www.gnu.org/licenses/agpl-3.0.md"
33
+MKIT_STUB_LICENSES[FDLv1.3]="http://www.gnu.org/licenses/fdl-1.3.md"
34
+MKIT_STUB_LICENSES[FDLv1.2]="http://www.gnu.org/licenses/old-licenses/fdl-1.2.md"
35
+MKIT_STUB_LICENSES[FDLv1.1]="http://www.gnu.org/licenses/old-licenses/fdl-1.1.md"
36
+
37
+
38
+deploy() {
39
+    local file=$1       # which known file?
40
+    local any_name=${NiceName:-$PackageName}
41
+    local tmp
42
+    tmp=$(mktemp -t mkit.stub.deploy.XXXXXXX)
43
+    mkdir -p "$(dirname "$file")"
44
+    case $file in
45
+
46
+        Makefile)
47
+            echo -n "# $any_name"
48
+            test -n "$Tagline" && echo -n " - $Tagline"
49
+            echo
50
+            $MkLicense && echo '# See LICENSE.md file for copyright and license details.'
51
+            echo ''
52
+            echo 'MKIT_DIR=utils/mkit'
53
+            #shellcheck disable=SC2016
54
+            echo 'include $(MKIT_DIR)/mkit.mk'
55
+            ;;
56
+
57
+        README.md)
58
+            echo "$any_name"
59
+            tr -c '=\n' '=' <<<"$any_name"
60
+            echo ''
61
+            echo ''
62
+            if test -n "$Tagline"; then
63
+                echo "$Tagline"
64
+            else
65
+                echo "(Nothing to say about this project.)"
66
+            fi
67
+            ;;
68
+
69
+        */mkit.ini|mkit.ini)
70
+            echo "[project]"
71
+            echo "    version     = $Version"
72
+            test -n "$Codename"     && echo "    codename    = $Codename"
73
+            test -n "$NiceName"     && echo "    name        = $NiceName"
74
+            test -n "$Tagline"      && echo "    tagline     = $Tagline"
75
+            test -n "$PackageName"  && echo "    pkgname     = $PackageName"
76
+            test -n "$Maintainer"   && echo "    maintainer  = $Maintainer"
77
+            test -n "$VcsBrowser"   && echo "    vcs_browser = $VcsBrowser"
78
+            test -n "$RelSrc"       && echo "    relsrc      = $RelSrc"
79
+            test -n "$RelDst"       && echo "    reldst      = $RelDst"
80
+            if updating; then
81
+                remake_section dist
82
+                remake_section ENV
83
+                remake_section roots
84
+                remake_section tokens
85
+                remake_section modes
86
+                remake_section files
87
+            else
88
+                echo ""
89
+                echo "[dist]"
90
+                $MkLicense  && echo "    tarball = LICENSE.md"
91
+                $MkMakefile && echo "    tarball = Makefile"
92
+                $MkReadme   && echo "    tarball = README.md"
93
+                echo "    tarball = mkit.ini"
94
+                $MkPackaging && echo "    tarball = packaging"
95
+                echo "    tarball = src"
96
+                echo "    tarball = tests"
97
+                echo "    tarball = utils"
98
+                $MkPackaging && echo "    rpmstuff = packaging/template.spec"
99
+                $MkPackaging && echo "    debstuff = packaging/debian"
100
+                echo ""
101
+                echo "[ENV]"
102
+                echo "    PREFIX = /usr/local"
103
+                echo ""
104
+                echo "[roots]"
105
+                echo "    bin     = [ENV:PREFIX]/bin"
106
+                echo "    doc     = [ENV:PREFIX]/share/doc/$PackageName"
107
+                echo ""
108
+                echo "[tokens]"
109
+                echo "    __${PackageName^^}_FOO__ = Barr.."
110
+                echo ""
111
+                echo "[modes]"
112
+                echo "    bin     = 755"
113
+                echo "    doc     = 644"
114
+                echo ""
115
+                echo "[files]"
116
+                echo "    bin      = src/$PackageName"
117
+                $MkLicense && echo "    doc      = LICENSE.md"
118
+                $MkReadme  && echo "    doc      = README.md"
119
+            fi
120
+            echo ""
121
+            echo "#mkit version=$MKIT_VERSION"
122
+            ;;
123
+
124
+        packaging/template.spec)
125
+            echo 'Name:		__MKIT_PROJ_PKGNAME__'
126
+            echo 'Version:	__MKIT_PROJ_VERSION__'
127
+            echo 'Release:	1%{?dist}'
128
+            echo 'Summary:	__MKIT_PROJ_NAME__ - __MKIT_PROJ_TAGLINE__'
129
+            echo ''
130
+            $MkLicense && echo "License:	$License"
131
+            echo 'Source0:	%{name}-%{version}.tar.gz'
132
+            echo ''
133
+            echo 'BuildArch:	noarch'
134
+            echo 'BuildRequires:	coreutils git'
135
+            echo 'Requires:	MKIT_STUB_REQUIRES'
136
+            echo ''
137
+            echo '%description'
138
+            echo 'MKIT_STUB_DESCRIPTION'
139
+            echo ''
140
+            echo '%prep'
141
+            echo '%setup -q'
142
+            echo ''
143
+            echo '%build'
144
+            echo 'make %{?_smp_mflags} PREFIX=/usr'
145
+            echo ''
146
+            echo '%install'
147
+            echo '%make_install PREFIX=/usr'
148
+            echo ''
149
+            echo '%files'
150
+            echo 'MKIT_STUB_FILELIST'
151
+            echo ''
152
+            echo '%changelog'
153
+            echo ''
154
+            echo '# specfile built with MKit __MKIT_SELF_VERSION__'
155
+            ;;
156
+
157
+        packaging/debian/copyright)
158
+            echo ""
159
+            ;;
160
+
161
+        packaging/debian/control)
162
+            echo 'Source: __MKIT_PROJ_PKGNAME__'
163
+            echo 'Maintainer: __MKIT_PROJ_MAINTAINER__'
164
+            test -n "$VcsBrowser" && echo 'Vcs-Browser: __MKIT_PROJ_VCS_BROWSER__'
165
+            echo 'Section: misc'
166
+            echo 'Priority: extra'
167
+            echo 'Standards-Version: 3.9.2'
168
+            echo 'Build-Depends: debhelper (>= 9)'
169
+            echo ''
170
+            echo 'Package: __MKIT_PROJ_PKGNAME__'
171
+            echo 'Architecture: all'
172
+            echo 'Depends: MKIT_STUB_REQUIRES'
173
+            echo 'Description: __MKIT_PROJ_NAME__ - __MKIT_PROJ_TAGLINE__'
174
+            echo ' MKIT_STUB_DESCRIPTION'
175
+            echo ''
176
+            echo '# control file built with MKit __MKIT_SELF_VERSION__'
177
+            ;;
178
+
179
+        packaging/debian/changelog)
180
+            echo '__MKIT_PROJ_PKGNAME__ (__MKIT_PROJ_VERSION__-1) UNRELEASED; urgency=medium'
181
+            echo ''
182
+            echo '  * Initial release. (Closes: #XXXXXX)'
183
+            echo ''
184
+            echo " -- __MKIT_PROJ_MAINTAINER__  $(date -R)"
185
+            ;;
186
+
187
+        packaging/debian/compat)
188
+            echo 9
189
+            ;;
190
+
191
+        packaging/debian/rules)
192
+            echo '#!/usr/bin/make -f'
193
+            echo ''
194
+            echo '%:'
195
+            echo ''
196
+            echo '	dh $@'
197
+            echo ''
198
+            echo 'override_dh_auto_install:'
199
+            echo ''
200
+            echo '	make install PREFIX=/usr DESTDIR=debian/tmp'
201
+            echo ''
202
+            echo 'override_dh_usrlocal:'
203
+            echo ''
204
+            echo '	@true'
205
+            ;;
206
+
207
+        packaging/debian/source/format)
208
+            echo '3.0 (quilt)'
209
+            ;;
210
+
211
+        packaging/debian/*.install)
212
+            echo MKIT_STUB_FILELIST
213
+            ;;
214
+
215
+        src/*.skel)
216
+            echo 'echo "my version is: __MKIT_PROJ_VERSION__"'
217
+            echo 'echo "And that'"'"'s all, folks!"'
218
+            ;;
219
+
220
+        LICENSE.md)
221
+            local url   # license URL
222
+            url="${MKIT_STUB_LICENSES[$License]}"
223
+            curl -sf "$url" \
224
+             || die "failed to download license: $url"
225
+            ;;
226
+
227
+        .mkit/autoclean)
228
+            ;;
229
+
230
+        MKIT_STUB_README.md)
231
+            echo "FINISHING MKIT CONFIGURATION"
232
+            echo "============================"
233
+            echo ""
234
+            echo "Congratulations, your new project has been configured!"
235
+            echo ""
236
+            echo "However, the *stub* script is not able to figure out"
237
+            echo "everything, so few things still need to be done manually."
238
+            echo "This document will guide you throught the rest of the"
239
+            echo "process."
240
+
241
+            echo ""
242
+            echo ""
243
+            echo "Structure"
244
+            echo "---------"
245
+            echo ""
246
+            echo "First, let's go through the directory structure:"
247
+            echo ""
248
+            echo " *  *src* directory - here is your main place to store"
249
+            echo "    source files.  This includes also documents like user"
250
+            echo "    manuals---IOW, anything intended to end up on user's"
251
+            echo "    machine should be uder 'src'."
252
+            echo ""
253
+            echo "    Note that during build time, files named ending with"
254
+            echo "    '.skel' are subject to token expansion, see mkit.ini"
255
+            echo "    section below for details."
256
+            echo ""
257
+            echo " *  *notes* directory - here you shall store notes"
258
+            echo "    intended for people contributing to your project,"
259
+            echo "    for instance, guidelines, coding style documents,"
260
+            echo "    TODOs, ideas, plans..."
261
+            echo ""
262
+            echo " *  *utils* directory - here you shall store utilities"
263
+            echo "    and scripts that will help you with project maintenance,"
264
+            echo "    and that, unlike software like compilers or versioning"
265
+            echo "    systems, can (and should) be embedded inside the"
266
+            echo "    repository."
267
+            echo ""
268
+            echo "    MKit itself is one nice example. :)"
269
+
270
+            if $MkPackaging; then
271
+            echo ""
272
+            echo " *  *packaging* directory contains templates that enable"
273
+            echo "    MKit create raw stuffs used to create DEB or RPM"
274
+            echo "    packages.  Similar to '.skel' files in 'src', all files"
275
+            echo "    here are automatically considered for token expansion,"
276
+            echo "    no matter how they are named (see mkit.ini section"
277
+            echo "    below)."
278
+            echo ""
279
+            echo "    NOTE: these templates, as well as any packages created by"
280
+            echo "    them are intended only for experimental, private use and"
281
+            echo "    testing."
282
+            echo ""
283
+            echo "    Should you have ambition to create 'real' packages for"
284
+            echo "    OS distribution such as Debian or Fedora (what a great"
285
+            echo "    idea!), be prepared that you will need to follow their"
286
+            echo "    guidelines.  This will most probably mean huge changes"
287
+            echo "    to these packages or even changes to your workflow."
288
+
289
+            echo ""
290
+            echo ""
291
+            echo "Placeholders"
292
+            echo "------------"
293
+            echo ""
294
+            echo "At places where *stub* script did not have way to get all"
295
+            echo "information automatically, it has inserted placeholders."
296
+            echo "You will need to go through all of these placeholders and"
297
+            echo "replace them with proper data."
298
+            echo ""
299
+            echo "Please follow instructions:"
300
+            echo ""
301
+            echo " 1. Look for placeholders starting with \`MKIT_STUB_\`"
302
+            echo "    prefix by calling this command:"
303
+            echo ""
304
+            echo "        grep -l MKIT_STUB_ -r"
305
+            echo ""
306
+            echo " 2. Go through each file and locate the placeholder.  (You"
307
+            echo "    will also see placeholders like \`__MKIT_*__\`, you can"
308
+            echo "    ignore those."
309
+            echo ""
310
+            echo " 3. Replace placeholder with appropriate information:"
311
+            echo ""
312
+            echo "     *  \`MKIT_STUB_REQUIRES\` - Requirements of your"
313
+            echo "        project."
314
+            echo ""
315
+            echo "     *  \`MKIT_STUB_DESCRIPTION\` - Description of your"
316
+            echo "        project (few sentences to paragraphs)."
317
+            echo ""
318
+            echo "     *  \`MKIT_STUB_FILELIST\` - List of full paths to"
319
+            echo "        your files after installation."
320
+            echo ""
321
+            echo "        Note that in case of debian/package.install files,"
322
+            echo "        PREFIX based paths (eg. /usr/bin) in this file should"
323
+            echo "        should be as if PREFIX was /usr."
324
+            echo ""
325
+            echo "        In case of Fedora-based distro, you should make use"
326
+            echo "        of RPM macros:"
327
+            echo ""
328
+            echo "            https://fedoraproject.org/wiki/Packaging:RPMMacros"
329
+            echo ""
330
+            echo "    Refer to these documents for further details:"
331
+            echo ""
332
+            echo "        http://rpm-guide.readthedocs.io/"
333
+            echo "        https://www.debian.org/doc/manuals/maint-guide/"
334
+            fi
335
+
336
+            echo ""
337
+            echo ""
338
+            echo "mkit.ini"
339
+            echo "--------"
340
+            echo ""
341
+            echo "Most sections still need to be reviewed. In order to do"
342
+            echo "that, you will need to understand how MKit works:"
343
+            echo ""
344
+            echo " 1. First, you need to define *roles* your files will play"
345
+            echo "    when they are installed on user's file systems.  These"
346
+            echo "    roles then imply where and how the files should be"
347
+            echo "    deployed."
348
+            echo ""
349
+            echo "    Typical example of a role is e.g. 'bin' for commands"
350
+            echo "    (normally under '/usr/bin' or '/usr/local/bin'), 'doc'"
351
+            echo "    for documents or 'lib' for libraries."
352
+
353
+            echo ""
354
+            echo " 2. Next, in \`[roots]\` section, you have to set target"
355
+            echo "    root directory for each role.  However, in order to"
356
+            echo "    enable people to implement local conventions, it is"
357
+            echo "    considered a good manner to also respect PREFIX"
358
+            echo "    environment variable.  For this reason, most paths"
359
+            echo "    need to start with \`[ENV:PREFIX]\`."
360
+            echo ""
361
+
362
+            echo " 3. \`[files]\` section is where you assign actual files"
363
+            echo "    from your repository to their final paths.  The format"
364
+            echo "    is \`ROLE = REPOPATH [RENAMED]\`, where ROLE is file's"
365
+            echo "    role, REPOPATH is relative path to the file."
366
+            echo ""
367
+            echo "    Final path is then composed by taking path assigned to"
368
+            echo "    ROLE and appending file's name.  However, if you need"
369
+            echo "    the deployed file to have different name than in the"
370
+            echo "    codebase, you can specify the other name as RENAMED."
371
+            echo ""
372
+            echo "    Note that you don't need to address every single file"
373
+            echo "    individually, if in your repo you have a directory with"
374
+            echo "    100 files of the same role, you can add just path to the"
375
+            echo "    directory itself."
376
+
377
+            echo ""
378
+            echo " 4. If some roles require special permissions on your files,"
379
+            echo "    \`[modes]\` section is your friend.  Permissions here"
380
+            echo "    should be in UNIX octal format."
381
+
382
+            echo ""
383
+            echo " 5. Next, \`[tokens]\` section allows you to define own"
384
+            echo "    placeholders that will be replaced when your scripts are"
385
+            echo "    built.  Each file in 'src' directory that is named with"
386
+            echo "    '.skel' suffix, and each file from 'packaging' directory"
387
+            echo "    (no matter its name), can contain one or more of tokens"
388
+            echo "    defined here, plus range of tokens automatically defined"
389
+            echo "    by MKit.  During build, these tokens are replaced with"
390
+            echo "    their actual values."
391
+
392
+            echo ""
393
+            echo " 6. Less interesting, but important section is \`[dist]\`,"
394
+            echo "    which lists files in your codebase that will be added"
395
+            echo "    to distribution tarball (part of \"stuffs\" mentioned"
396
+            echo "    above).  Listing directory here will include all its"
397
+            echo "    contents, and normally it's OK to be very inclusive, so"
398
+            echo "    most of the time this section should be OK."
399
+
400
+            echo ""
401
+            echo " 7. Even less interesting is section \`[ENV]\`.  It is"
402
+            echo "    special in that it provides *default* value for an"
403
+            echo "    environment variable.  You almost never need to touch"
404
+            echo "    this."
405
+            echo ""
406
+
407
+            echo " 8. Finally, the most interesting section!  \`[project]\`,"
408
+            echo "    provides most general information for your project such"
409
+            echo "    as name and version."
410
+            echo ""
411
+            echo "    Note that the \`version\` key is another \"special"
412
+            echo "    snowflake\" -- it is now set to 0.0.0, and you **should"
413
+            echo "    not need** to change  it manually.  When you feel you"
414
+            echo "    a are ready to release next version of your evolving"
415
+            echo "    project, simply call \`make vbump\` and MKit will take"
416
+            echo "    care of everything!"
417
+
418
+            if $MkMakefile; then
419
+            echo ""
420
+            echo ""
421
+            echo "Makefile"
422
+            echo "--------"
423
+            echo ""
424
+            echo "*stub* script also created a Makefile for you, but all"
425
+            echo "it really does is include MKit's own mkit.mk, which in turn"
426
+            echo "only maps \`make\` targets to actual mkit script calls."
427
+            echo "Unless your project already uses GNU Make, you should not"
428
+            echo "need to change this file."
429
+            fi
430
+
431
+            if $MkReadme; then
432
+            echo ""
433
+            echo ""
434
+            echo "README.md"
435
+            echo "---------"
436
+            echo ""
437
+            echo "Each serious project needs a serious README.  Which is why"
438
+            echo "*stub* has created a 'stub' of one for you."
439
+            fi
440
+
441
+            echo ""
442
+            echo ""
443
+            echo "The final touch"
444
+            echo "---------------"
445
+            echo ""
446
+            echo "Once you have reviewed everything, just delete this file!"
447
+            ;;
448
+
449
+    esac >"$tmp"
450
+    cat "$tmp" > "$file"
451
+    rm "$tmp"
452
+}
453
+
454
+known_licenses() {
455
+    local key
456
+    local first=true
457
+    for key in "${!MKIT_STUB_LICENSES[@]}"; do
458
+        $first && echo "$key"  && continue
459
+        echo ", $key"
460
+    done
461
+}
462
+
463
+usage() {
464
+    {
465
+        echo "Usage:"
466
+        echo "   stub [options] new PKGNAME"
467
+        echo "   stub [options] update"
468
+        echo "   stub -L"
469
+        echo ""
470
+        echo "Options:"
471
+        echo ""
472
+        echo "    -c CODENAME   your project codename"
473
+        echo "    -t TAGLINE    your project tagline"
474
+        echo "    -b RELSRC     pre-release branch"
475
+        echo "    -B RELDST     post-release branch"
476
+        echo "    -n NICENAME   your project's 'nice' name"
477
+        echo "    -l LICENSE    your options's license (see -L)"
478
+        echo "    -m MAINT      project maintainer's name and e-mail"
479
+        echo "    -v URL        URL to public code browser"
480
+        echo "    -V VERSION    initial version (default: 0.0.0)"
481
+        echo "    -a            enable autoclean ('make clean' after"
482
+        echo "                  each 'make install')"
483
+        echo "    -g            make git commits before and adter"
484
+        echo "                  (implies -y)"
485
+        echo "    -y            don't ask, just do it"
486
+        echo "    -R            skip creating README.md"
487
+        echo "    -M            skip creating Makefile"
488
+        echo "    -P            skip creating packaging templates"
489
+        echo "    -L            list know licenses and exit"
490
+        echo ""
491
+        echo "PKGNAME should be packaging-friendly name, ie. consist"
492
+        echo "only of small letters, numbers, underscore and dash."
493
+        echo "For your 'real' name, use NICENAME, which can be any"
494
+        echo "string."
495
+    } >&2
496
+    exit 2
497
+}
498
+
499
+confirm() {
500
+    local response      # user's response to our warning
501
+    $Force && return 0
502
+    {
503
+        echo "Warning: This operation can be destructive for your"
504
+        echo "current codebase.  At least following files will be"
505
+        echo "created or overwritten:"
506
+        echo ""
507
+        $MkPackaging    && echo " *  'packaging' directory (pass -P to avoid)"
508
+        $MkMakefile     && echo " *  'Makefile' (pass -M to avoid)"
509
+        $MkReadme       && echo " *  'README.md' (pass -R to avoid)"
510
+        $MkLicense      && echo " *  'LICENSE.md' (omit -l to avoid)"
511
+        echo " *  'mkit.ini'"
512
+        echo ""
513
+        read -p "Type 'yes' to proceed: " -r response
514
+    } >&2
515
+    test "$response" == "yes" && return 0
516
+    warn "Aborting."
517
+    return 1
518
+}
519
+
520
+mkcommit_backup() {
521
+    git ls-files --others \
522
+      | grep -qv -e '^utils/mkit$' -e '^utils/mkit/' \
523
+     || { warn "nothing to back up"; return 0; }
524
+    git add .                           || return
525
+    git rm -r --cached utils/mkit       || return
526
+    git commit -m "WIP [mkit/stub] backup" || return
527
+}
528
+
529
+mkcommit_mkit_code() {
530
+    git ls-files --others \
531
+      | grep -q -e '^utils/mkit$' -e '^utils/mkit/' \
532
+     || return 0
533
+    git add utils/mkit || return
534
+    git commit -m "WIP [mkit/stub] Add MKit version v$MKIT_VERSION" || return
535
+}
536
+
537
+mkcommit_mkit_conf() {
538
+    local msg       # commit message (the important art
539
+    git add . || return
540
+    case $Action in
541
+        new)    msg="Add MKit configuration stub" ;;
542
+        update) msg="Update MKit configuration"   ;;
543
+    esac
544
+    git commit -m "WIP [mkit/stub] $msg" || return
545
+}
546
+
547
+deploy_packaging() {
548
+    rm -rf packaging
549
+    deploy packaging/template.spec
550
+    deploy packaging/debian/copyright
551
+    deploy packaging/debian/control
552
+    deploy packaging/debian/changelog
553
+    deploy packaging/debian/compat
554
+    deploy packaging/debian/rules
555
+    deploy packaging/debian/source/format
556
+    deploy packaging/debian/"$PackageName".install
557
+}
558
+
559
+init_from_existing() {
560
+    #
561
+    # Initialize variables from old mkit.ini
562
+    #
563
+    test -f "$MKIT_INI" \
564
+     || die "mkit.ini not found; aborting update: $MKIT_INI"
565
+    user_gave Codename    || Codename=$(ini_raw1v project:codename)
566
+    user_gave License     || License=$(ini_raw1v project:license)
567
+    user_gave Maintainer  || Maintainer=$(ini_raw1v project:maintainer)
568
+    user_gave NiceName    || NiceName=$(ini_raw1v project:name)
569
+    user_gave PackageName || PackageName=$(ini_raw1v project:pkgname)
570
+    user_gave RelDst      || RelDst=$(ini_raw1v project:reldst)
571
+    user_gave RelSrc      || RelSrc=$(ini_raw1v project:relsrc)
572
+    user_gave Tagline     || Tagline=$(ini_raw1v project:tagline)
573
+    user_gave VcsBrowser  || VcsBrowser=$(ini_raw1v project:vcs_browser)
574
+    user_gave Version     || Version=$(ini_raw1v project:version)
575
+}
576
+
577
+ini_raw1v() {
578
+    #
579
+    # Read raw scalar from mkit.ini
580
+    #
581
+    local path=$1
582
+    MKIT_INI_EXPAND=0 ini 1value "$path"
583
+}
584
+
585
+user_gave() {
586
+    #
587
+    # True if user gave value to variable $1
588
+    #
589
+    local var=$1    # name of the variable
590
+    { test "${UserGave[$var]}" == 1; } 2>/dev/null
591
+}
592
+
593
+updating() {
594
+    #
595
+    # Are we updating?
596
+    #
597
+    test "$Action" == update
598
+}
599
+
600
+remake_section() {
601
+    #
602
+    # Re-compose mkit.ini section $1
603
+    #
604
+    local section=$1
605
+    local key
606
+    local value
607
+    ini lskeys "$section" | grep -q . \
608
+     || return 1
609
+    echo ""
610
+    echo "[$section]"
611
+    ini lskeys "$section" \
612
+      | while read -r key; do
613
+            MKIT_INI_EXPAND=0 ini values "$section:$key" \
614
+              | while read -r value; do
615
+                    echo "$key = $value"
616
+                done
617
+        done \
618
+      | column -to' ' \
619
+      | sed 's/^/    /'
620
+}
621
+
622
+main() {
623
+    local NiceName          # human-readable project name
624
+    local PackageName       # machine-safe project (package) name
625
+    local RelSrc            # pre-release branch
626
+    local RelDst            # post-release branch
627
+    local Codename          # release codename
628
+    local Tagline           # project tagline
629
+    local Maintainer        # project maintainer (Name + e-mail)
630
+    local VcsBrowser        # VCS browser (eg. GitHub URL)
631
+    local Version=0.0.0     # project version
632
+    local AutoClean=false   # touch .mkit/autoclean?
633
+    local MkCommits=false   # create pre/post git commits?
634
+    local Force=false       # go without asking?
635
+    local MkReadme=true     # create README.md?
636
+    local MkMakefile=true   # create Makefile?
637
+    local MkPackaging=true  # create packaging templates?
638
+    local MkLicense=false   # create LICENSE.md file
639
+    local Action            # 'update' to respect existing, 'new' to force
640
+                            # rewrite incl. MKIT_STUB_* placeholders
641
+    declare -A UserGave
642
+    while true; do case $1 in
643
+        -n) NiceName=$2;   UserGave[NiceName]=1;   shift 2 || usage ;;
644
+        -b) RelSrc=$2;     UserGave[RelSrc]=1;     shift 2 || usage ;;
645
+        -B) RelDst=$2;     UserGave[RelDst]=1;     shift 2 || usage ;;
646
+        -c) Codename=$2;   UserGave[Codename]=1;   shift 2 || usage ;;
647
+        -t) Tagline=$2;    UserGave[Tagline]=1;    shift 2 || usage ;;
648
+        -l) License=$2;    UserGave[License]=1;    shift 2 || usage ;;
649
+        -m) Maintainer=$2; UserGave[Maintainer]=1; shift 2 || usage ;;
650
+        -v) VcsBrowser=$2; UserGave[VcsBrowser]=1; shift 2 || usage ;;
651
+        -V) Version=$2;    UserGave[Version]=1;    shift 2 || usage ;;
652
+        -M) MkMakefile=false;   shift ;;
653
+        -R) MkReadme=false;     shift ;;
654
+        -a) AutoClean=true;     shift ;;
655
+        -y) Force=true;         shift ;;
656
+        -g) MkCommits=true;     shift ;;
657
+        -P) MkPackaging=false;  shift ;;
658
+        -L) known_licenses | tr , '\n'; exit 0 ;;
659
+        -*) usage ;;
660
+        *)  break ;;
661
+    esac done
662
+    Action=$1; PackageName=$2
663
+    case $Action:$PackageName in
664
+        new:)     usage ;;
665
+        new:*)    :     ;;
666
+        update:)  :     ;;
667
+        update:*) usage ;;
668
+        *)        usage ;;
669
+    esac
670
+    updating && init_from_existing
671
+    if test -n "$License"; then
672
+        known_licenses | grep -qxF "$License" \
673
+         || die "unknown license (use -L to get list): $License"
674
+        MkLicense=true
675
+    fi
676
+    if $MkCommits; then
677
+        mkcommit_backup || die "failed creating backup commit"
678
+        Force=true
679
+    fi
680
+    confirm            || return 1
681
+    deploy "$MKIT_INI"
682
+    deploy src/"$PackageName".skel
683
+    $MkMakefile     && deploy Makefile
684
+    $MkReadme       && deploy README.md
685
+    $MkLicense      && deploy LICENSE.md
686
+    $AutoClean      && deploy .mkit/autoclean
687
+    $MkPackaging    && deploy_packaging
688
+    if $MkCommits; then
689
+        mkcommit_mkit_code || die "failed creating post-commit"
690
+        mkcommit_mkit_conf || die "failed creating post-commit"
691
+    fi
692
+    deploy MKIT_STUB_README.md
693
+    warn "Configuration stub built, follow instructions in"
694
+    warn "MKIT_STUB_README.md to finish configuration."
695
+    return 0
696
+}
697
+
698
+main "$@"