Alois Mahdal пре 7 година
родитељ
комит
b783a7e838

+ 48
- 36
utils/mkit/include/build.sh Прегледај датотеку

@@ -1,16 +1,18 @@
1 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 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 16
     test -n "$dstpath"  || dstpath=${srcpath%.skel}
15 17
     test -n "$ftype"    || ftype=$(_guess_ftype "$dstpath")
16 18
     debug_var srcpath dstpath ftype
@@ -21,13 +23,14 @@ _build1() {
21 23
 
22 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 29
     case $ftype in
28 30
         MKIT_COMMON)    _expand_tokens "tokens" ;;
29 31
         markdown)       _expand_includes | _expand_tokens "tokens" ;;
30 32
         rpmstuff)       _expand_tokens "tokens" "rpmstuff:tokens" ;;
33
+        debstuff)       _expand_tokens "tokens" "debstuff:tokens" ;;
31 34
         *)              die "unknown file type: $ftype" ;;
32 35
     esac
33 36
 }
@@ -59,17 +62,18 @@ _expand_includes() {
59 62
 
60 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 74
             debug_var section
70 75
             ini lskeys "$section" \
71
-              | while read varname;
72
-                do
76
+              | while read -r varname; do
73 77
                     varvalue="$(ini 1value "$section:$varname" | _qfs )"
74 78
                     echo "s|$varname|$varvalue|g;"
75 79
                     debug_var varname varvalue
@@ -77,6 +81,7 @@ _expand_tokens() {
77 81
         done
78 82
         echo "s|__MKIT_PROJ_NAME__|$(ini 1value project:name | _qfs)|g;"
79 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 85
         echo "s|__MKIT_PROJ_PKGNAME__|$(ini 1value project:pkgname | _qfs)|g;"
81 86
         echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | _qfs)|g;"
82 87
         echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | _qfs)|g;"
@@ -93,7 +98,7 @@ _guess_ftype() {
93 98
     #
94 99
     # Guess file type from destination path $1
95 100
     #
96
-    local dstpath="$1"
101
+    local dstpath=$1    # destination path
97 102
     case $dstpath in
98 103
         *.md) echo markdown    ;;
99 104
         *)    echo MKIT_COMMON ;;
@@ -114,21 +119,22 @@ build() {
114 119
     #
115 120
     # Add meat to all skeletons
116 121
     #
117
-    local srcpath
122
+    local srcpath   # each source path
118 123
     find -type f -name '*.skel' \
119
-     | while read srcpath;
120
-       do
124
+     | while read -r srcpath; do
121 125
            _build1 "$srcpath"
122 126
        done
123 127
 }
124 128
 
125 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 136
         ini lskeys "files:man" \
130
-          | while read manfile;
131
-            do
137
+          | while read -r manfile; do
132 138
                 mdfile="$manfile.md"
133 139
                 ronn -r "$mdfile"
134 140
                 mkdir -p "$MKIT_LOCAL"
@@ -157,7 +163,11 @@ debstuff() {
157 163
     #
158 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 172
     # tarball - we should already have by means of 'dist'
163 173
     #
@@ -168,17 +178,15 @@ debstuff() {
168 178
 
169 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 182
     test -n "$debian_skel" || die "dist:debstuff not specified"
173 183
     test -d "$debian_skel" || die "debian directory template found: $debian_skel"
174 184
     mkdir -p debian/source
175
-    local dfsrc dftgt
176 185
     find "$debian_skel" -type f \
177
-      | while read dfsrc;
178
-        do
186
+      | while read -r dfsrc; do
179 187
             dftgt="debian/${dfsrc#$debian_skel}"
180 188
             mkdir -p "$(dirname "$dftgt")"
181
-            _build1 "$dfsrc" "$dftgt"
189
+            _build1 "$dfsrc" "$dftgt" debstuff
182 190
         done
183 191
     echo debian >> "$MKIT_LOCAL/built.lst"
184 192
 }
@@ -190,9 +198,12 @@ dist() {
190 198
     #FIXME: lacking Makefile skills, we do this step twice fot
191 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 207
     mkdir -p "$dirname"
197 208
     ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
198 209
     update_version "$version" "$dirname/mkit.ini"
@@ -209,9 +220,10 @@ rpmstuff() {
209 220
     #
210 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 226
     test -n "$specsrc" || die "dist:rpmstuff not specified"
215 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 Прегледај датотеку

@@ -1,4 +1,8 @@
1 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 7
 _deploy_item() {
4 8
     #
@@ -23,17 +27,17 @@ _deploy_item() {
23 27
     # Directories are copied recursively, and mode is
24 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 41
             done
38 42
     else
39 43
         _maybe install -DTvm "$mode" "$src" "$dst"
@@ -44,9 +48,9 @@ _get_dst() {
44 48
     #
45 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 54
     test -n "$dst" || dst=${src##*/}
51 55
     echo "$(_get_root "$grp")/$dst"
52 56
 }
@@ -55,9 +59,11 @@ _get_root() {
55 59
     #
56 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 67
     destdir=${destdir%/}
62 68
     case $destdir:$root in
63 69
         *:)     die "missing in config.ini: roots:$grp" ;;
@@ -84,16 +90,17 @@ install() {
84 90
     #
85 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 97
     ini lskeys "files" \
89 98
       | sort \
90 99
       | uniq \
91
-      | while read group;
92
-        do
100
+      | while read -r group; do
93 101
             mode=$(ini 1value "modes:$group")
94 102
             ini values "files:$group" \
95
-              | while read src dst;
96
-                do
103
+              | while read -r src dst; do
97 104
                     dst=$(_get_dst "$group" "$src" "$dst")
98 105
                     _deploy_item "$src" "$dst" "$mode"
99 106
                 done
@@ -106,15 +113,15 @@ uninstall() {
106 113
     #
107 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 119
     ini lskeys "files" \
111 120
       | sort \
112 121
       | uniq \
113
-      | while read group;
114
-        do
122
+      | while read -r group; do
115 123
             ini values "files:$group" \
116
-              | while read src dst;
117
-                do
124
+              | while read -r src dst; do
118 125
                     dst=$(_get_dst "$group" "$src" "$dst")
119 126
                     _maybe rm -vrf "$dst"
120 127
                 done

+ 21
- 14
utils/mkit/include/facts.sh Прегледај датотеку

@@ -1,12 +1,14 @@
1 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 7
 git_bool() {
6 8
     #
7 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 12
     git_present || warn "can't give bool outside git repo: $bool_name"
11 13
     case "$bool_name" in
12 14
         dirty_files)
@@ -29,7 +31,7 @@ git_fact() {
29 31
     #
30 32
     # Get git fact $1
31 33
     #
32
-    local fact_name="$1"
34
+    local fact_name=$1      # name of fact to get
33 35
     git_present || warn "can't give fact outside git repo: $fact_name"
34 36
     case "$fact_name" in
35 37
         latest_tag)
@@ -88,9 +90,9 @@ git_lasthash() {
88 90
     # work if you got outside the git repo in other way than dist
89 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 96
         echo -n "$last_hash"
95 97
         git_bool dirty && echo -n ".dirty"
96 98
     else    # we are outside (eg. distributor's build dir')
@@ -146,18 +148,23 @@ semver() {
146 148
     # FIXME:  Using project:prerl for release IDs may not be compatible with
147 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 161
     if git_present;
153 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 164
         if ! git describe --tags --exact-match HEAD >&/dev/null;
156 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 167
         fi
159
-        local dirty=""
160
-        local suffix=""
161 168
         git_bool dirty; dirty=$?
162 169
         test -n "$latest_tag" && version=${latest_tag:1}
163 170
         case "$dirty:$commit" in
@@ -165,7 +172,7 @@ semver() {
165 172
             0:)  suffix="+dirty"         ;;
166 173
             1:*) suffix="+$commit"       ;;
167 174
             0:*) suffix="+$commit.dirty" ;;
168
-            *)   suffix=MKIT_BUG;
175
+            *)   suffix=MKIT_BUG
169 176
                  warn "MKIT_BUG: bad dirt/commit detection" ;;
170 177
         esac
171 178
         test -n "$prerl" && suffix="-$prerl$suffix"

+ 34
- 32
utils/mkit/include/ini.sh Прегледај датотеку

@@ -1,11 +1,13 @@
1 1
 #!/bin/bash
2
+# MKit - simple install helper
3
+# See LICENSE file for copyright and license details.
2 4
 
3 5
 _ini_cat() {
4 6
     #
5 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 11
         printf -- "%s\n" "$line"
10 12
     done
11 13
 }
@@ -14,9 +16,11 @@ _ini_expand() {
14 16
     #
15 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 24
         suffix="${line#\[*\]}"              # /path
21 25
         ref="${line%$suffix}"               # [foo:bar]
22 26
         ref="${ref%\]}"                     # [foo:bar
@@ -30,7 +34,7 @@ _ini_grepkey() {
30 34
     #
31 35
     # Read key from a section
32 36
     #
33
-    local wnt=$1
37
+    local wnt=$1    # wanted key
34 38
     grep '.' \
35 39
       | grep -v '\s*#' \
36 40
       | sed -e 's/ *= */=/; s/ +$//; s/^//;' \
@@ -48,17 +52,15 @@ _ini_greppath() {
48 52
     #     [files:share]
49 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 64
     fi
63 65
     _ini_grepsec "$wntsec" | _ini_grepkey "$wntkey"
64 66
 }
@@ -67,12 +69,12 @@ _ini_grepsec() {
67 69
     #
68 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 75
     grep '.' \
73 76
       | grep -v '\s*#' \
74
-      | while read line;
75
-        do
77
+      | while read -r line; do
76 78
             case "$line" in
77 79
                 \[$wnt\]) ok=true;  continue ;;
78 80
                 \[*\])    ok=false; continue ;;
@@ -87,16 +89,15 @@ _ini_lskeys() {
87 89
     #
88 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 96
 _ini_maybe_expand() {
95 97
     #
96 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 101
         MKIT_INI_EXPAND=$(( --MKIT_INI_EXPAND )) _ini_expand
101 102
     else
102 103
         _ini_cat
@@ -107,10 +108,10 @@ ini() {
107 108
     #
108 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 115
     case $op in
115 116
         lskeys) fn=_ini_lskeys   ;;
116 117
         sec)    fn=_ini_grepsec  ;;
@@ -125,9 +126,10 @@ update_version() {
125 126
     #
126 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 133
     <"$inifile" perl -e '
132 134
         my $hit = 0;
133 135
         my $done = 0;

+ 42
- 22
utils/mkit/include/mkit.sh Прегледај датотеку

@@ -1,9 +1,34 @@
1 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 33
 _valid_targets() {
9 34
     #
@@ -15,11 +40,13 @@ _valid_targets() {
15 40
     echo debstuff
16 41
     echo dist
17 42
     echo install
43
+    echo release
18 44
     echo release_x
19 45
     echo release_y
20 46
     echo release_z
21 47
     echo rpmstuff
22 48
     echo uninstall
49
+    echo vbump
23 50
     echo vbump_x
24 51
     echo vbump_y
25 52
     echo vbump_z
@@ -38,9 +65,8 @@ debug_var() {
38 65
     # Print debug message
39 66
     #
40 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 71
             echo -n "MKIT_DEBUG: ${FUNCNAME[1]}():"
46 72
             echo -n " $__mkit_debug_var_name__"
@@ -50,14 +76,6 @@ debug_var() {
50 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 79
 _compver() {
62 80
     #
63 81
     # True if version $1 matches our version
@@ -65,8 +83,11 @@ _compver() {
65 83
     # If our x is 0, check first two fragments, otherwise check just
66 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 91
     their_x=${their_ver%%.*}
71 92
     their_y=${their_ver##$their_x.}
72 93
     their_y=${their_y%%.*}
@@ -89,12 +110,12 @@ _chkiniversion() {
89 110
     # Look for "#mkit version=0.0.0" or similar in first or last
90 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 115
     ver_line=$(
95 116
         {
96 117
             head -3 "$MKIT_INI"
97
-            tac "$MKIT_INI" | tail -3
118
+            tail -3 "$MKIT_INI"
98 119
         } | grep -m 1 -E '^# *mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
99 120
     )
100 121
     test -n "$ver_line" \
@@ -122,8 +143,7 @@ route() {
122 143
     #
123 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 147
         "$1"
128 148
     else
129 149
         {

+ 72
- 24
utils/mkit/include/release.sh Прегледај датотеку

@@ -1,20 +1,26 @@
1 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
 _bump_version() {
7 9
     #
8 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 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 24
     case $rlevel in
19 25
         x) new="$((oldx+MKIT_BUMPSIZE)).0.0"            ;;
20 26
         y) new="$oldx.$((oldy+MKIT_BUMPSIZE)).0"        ;;
@@ -28,23 +34,23 @@ _relck() {
28 34
     #
29 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 39
     case "$condition" in
34 40
         git_present)
35 41
             git rev-parse HEAD >&/dev/null\
36 42
              || die "cannot do this outside git repo"
37 43
             ;;
38 44
         at_relsrc)
39
-            local relsrc=$(ini 1value project:relsrc)
45
+            oracle=$(ini 1value project:relsrc)
40 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 50
         not_dirty)
45 51
             git diff --shortstat 2>/dev/null \
46 52
               | grep -q . \
47
-             && die "tree is dirty: $dirt"
53
+             && die "tree is dirty!"
48 54
             ;;
49 55
         tags_ok)
50 56
             git_fact latest_tag \
@@ -62,7 +68,7 @@ _relck() {
62 68
              && die "WIP commit since $(git_fact latest_tag)"
63 69
             ;;
64 70
         ini_version)
65
-            local oracle=$(git_fact latest_version | _bump_version "$rlevel")
71
+            oracle=$(git_fact latest_version | _bump_version "$rlevel")
66 72
             ini 1value project:version  \
67 73
               | grep -qFx "$oracle" \
68 74
              || die "new version not in mkit.ini: $oracle"
@@ -83,9 +89,10 @@ _release() {
83 89
     # FIXME: Using project:prerl as build.sh:semver() does may not be
84 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 97
     _relck git_present
91 98
     _relck at_relsrc
@@ -101,10 +108,10 @@ _release() {
101 108
     $MKIT_DRY && return
102 109
     git tag -m "$(_release_msg)" "$newtag"
103 110
 
111
+    relsrc=$(ini 1value project:relsrc)
104 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 115
         git branch -f "$reldst" "$newtag"
109 116
     fi
110 117
 }
@@ -127,8 +134,14 @@ _release_msg() {
127 134
 }
128 135
 
129 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 145
     _relck git_present
133 146
     _relck at_relsrc
134 147
     _relck not_dirty
@@ -143,6 +156,9 @@ _vbump() {
143 156
 }
144 157
 
145 158
 _vbump_gitmsg() {
159
+    #
160
+    # Compose git message template for 'Bump version' commit
161
+    #
146 162
     echo "Bump version"
147 163
     echo ""
148 164
     echo "Overview of changes:"
@@ -155,26 +171,58 @@ _vbump_gitmsg() {
155 171
         '
156 172
 }
157 173
 
174
+release() {
175
+    #
176
+    # Perform release on Z level
177
+    #
178
+    _release z
179
+}
180
+
158 181
 release_x() {
182
+    #
183
+    # Perform release on X level
184
+    #
159 185
     _release x
160 186
 }
161 187
 
162 188
 release_y() {
189
+    #
190
+    # Perform release on Y level
191
+    #
163 192
     _release y
164 193
 }
165 194
 
166 195
 release_z() {
196
+    #
197
+    # Perform release on Z level
198
+    #
167 199
     _release z
168 200
 }
169 201
 
202
+vbump() {
203
+    #
204
+    # Perform version bump on Z level
205
+    #
206
+    _vbump z
207
+}
208
+
170 209
 vbump_x() {
210
+    #
211
+    # Perform version bump on X level
212
+    #
171 213
     _vbump x
172 214
 }
173 215
 
174 216
 vbump_y() {
217
+    #
218
+    # Perform version bump on Y level
219
+    #
175 220
     _vbump y
176 221
 }
177 222
 
178 223
 vbump_z() {
224
+    #
225
+    # Perform version bump on Z level
226
+    #
179 227
     _vbump z
180 228
 }

+ 60
- 0
utils/mkit/include/vars.sh Прегледај датотеку

@@ -0,0 +1,60 @@
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 Прегледај датотеку

@@ -1,80 +1,32 @@
1 1
 #!/bin/bash
2
+#shellcheck disable=SC2034
2 3
 # mkit - simple install helper
3 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 19
 # Path to MKit dir (where 'include' is)
27 20
 #
28 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 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 30
 esac
79 31
 
80 32
 mkit_init

+ 7
- 1
utils/mkit/mkit.mk Прегледај датотеку

@@ -26,6 +26,9 @@ rpmstuff: dist
26 26
 install: all
27 27
 	@$(MKIT_DIR)/make install
28 28
 
29
+release:
30
+	@$(MKIT_DIR)/make release
31
+
29 32
 release_x:
30 33
 	@$(MKIT_DIR)/make release_x
31 34
 
@@ -38,6 +41,9 @@ release_z:
38 41
 uninstall:
39 42
 	@$(MKIT_DIR)/make uninstall
40 43
 
44
+vbump:
45
+	@$(MKIT_DIR)/make vbump
46
+
41 47
 vbump_x:
42 48
 	@$(MKIT_DIR)/make vbump_x
43 49
 
@@ -47,4 +53,4 @@ vbump_y:
47 53
 vbump_z:
48 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 Прегледај датотеку

@@ -0,0 +1,698 @@
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 "$@"