Browse Source

Update MKit to v0.0.56

Alois Mahdal 4 months ago
parent
commit
d24606de7c
8 changed files with 599 additions and 133 deletions
  1. 1
    1
      mkit.ini
  2. 191
    65
      utils/mkit/include/build.sh
  3. 44
    22
      utils/mkit/include/facts.sh
  4. 77
    16
      utils/mkit/include/mkit.sh
  5. 64
    1
      utils/mkit/include/vars.sh
  6. 25
    10
      utils/mkit/make
  7. 23
    4
      utils/mkit/mkit.mk
  8. 174
    14
      utils/mkit/stub

+ 1
- 1
mkit.ini View File

@@ -30,4 +30,4 @@
30 30
 [files]
31 31
     bin = src/app dummy
32 32
 
33
-#mkit version=0.0.40
33
+#mkit version=0.0.56

+ 191
- 65
utils/mkit/include/build.sh View File

@@ -14,7 +14,7 @@ __build1() {
14 14
     local dstpath=$2    # destination meaty animal path
15 15
     local ftype=$3      # file/builder type
16 16
     test -n "$dstpath"  || dstpath=${srcpath%.skel}
17
-    test -n "$ftype"    || ftype=$(__guess_ftype "$dstpath")
17
+    test -n "$ftype"    || ftype=MKIT_COMMON
18 18
     debug_var srcpath dstpath ftype
19 19
     <"$srcpath" __build1_ftype "$ftype" >"$dstpath"
20 20
     __rec_built "$dstpath"
@@ -26,16 +26,45 @@ __build1_ftype() {
26 26
     #
27 27
     local ftype=$1      # file/builder type
28 28
     case $ftype in
29
-        MKIT_COMMON)    __expand_macros "macros" ;;
30
-        rpmstuff)       __expand_macros "macros" "rpmstuff:macros" ;;
31
-        debstuff)       __expand_macros "macros" "debstuff:macros" ;;
29
+        MKIT_COMMON)    __expand_macros "build:macros" ;;
30
+        rpmstuff)       __expand_macros "rpmstuff:macros" ;;
31
+        debstuff)       __expand_macros "debstuff:macros" ;;
32
+        pystuff)        __expand_macros "pystuff:macros" ;;
32 33
         *)              die "unknown file type: $ftype" ;;
33 34
     esac
34 35
 }
35 36
 
37
+__macrol() {
38
+    #
39
+    # List known macros
40
+    #
41
+    find "${MacroDirs[@]}" -mindepth 1 -depth -printf '%P\n' \
42
+      | sed 's/[.]/:/g'
43
+}
44
+
45
+__macror() {
46
+    #
47
+    # Read macro $1
48
+    #
49
+    local key=$1
50
+    find "${MacroDirs[@]}" -mindepth 1 -depth -name "$key" \
51
+      | head -1 \
52
+      | xargs -r cat
53
+}
54
+
55
+__macrow() {
56
+    #
57
+    # Write stdin as macro $1
58
+    #
59
+    local fqkey=$1
60
+    local file="$MKIT_LOCAL/data/${fqkey//:/.}"
61
+    mkdir -p "${file%/*}"
62
+    cat >"$file"
63
+}
64
+
36 65
 __expand_line() {
37 66
     #
38
-    # Expand macro from $MacroMap in single line $1
67
+    # Expand macro from config in single line $1
39 68
     #
40 69
     # If macro value has multiple lines, repeat original line with
41 70
     # different substitution.
@@ -49,12 +78,12 @@ __expand_line() {
49 78
     local mvline    # line of macro value
50 79
     local xline     # expanded line
51 80
     xline=$line
52
-    for mname in "${!MacroMap[@]}"; do
81
+    for mname in $(__macrol); do
53 82
         if ! test "${line//$mname}" == "$line"; then
54 83
             xline=$(
55 84
                 while IFS= read -r mvline; do
56 85
                     echo "${line//$mname/$mvline}"
57
-                done <<<"${MacroMap[$mname]}"
86
+                done <<<"$(__macror "$mname")"
58 87
             )
59 88
         fi
60 89
         line=$xline
@@ -65,44 +94,25 @@ __expand_line() {
65 94
 
66 95
 __expand_macros() {
67 96
     #
68
-    # Read stdin, expanding macros from sections $@
97
+    # Read stdin, expanding macros from extra sections $@
69 98
     #
70
-    local section       # each section to expand macros from
99
+    local MacroDirs=()  # directories to lookup macros in
100
+    local mdir          # every ^^
71 101
     local line          # each line on stdin
72
-    local mname         # each macro name
73
-    local -A MacroMap   # macro value map
74
-    MacroMap[__MKIT_MKIT_VERSION__]=$MKIT_VERSION
75
-    MacroMap[__MKIT_PROJ_NAME__]=$(ini 1value project:name)
76
-    MacroMap[__MKIT_PROJ_CODENAME__]=$(ini 1value project:codename)
77
-    MacroMap[__MKIT_PROJ_LICENSE__]=$(ini 1value project:license)
78
-    MacroMap[__MKIT_PROJ_PKGNAME__]=$(ini 1value project:pkgname)
79
-    MacroMap[__MKIT_PROJ_TAGLINE__]=$(ini 1value project:tagline)
80
-    MacroMap[__MKIT_PROJ_MAINTAINER__]=$(ini 1value project:maintainer)
81
-    MacroMap[__MKIT_PROJ_VCS_BROWSER__]=$(ini 1value project:vcs_browser)
82
-    MacroMap[__MKIT_PROJ_GIT_LASTHASH__]=$(__cached git_lasthash)
83
-    MacroMap[__MKIT_PROJ_GIT_LASTSUMMARY__]=$(__cached git_lastsummary)
84
-    MacroMap[__MKIT_PROJ_VERSION__]=$(__cached semver)
85
-    for section in "$@"; do
86
-        for mname in $(ini lskeys "$section"); do
87
-            MacroMap[$mname]=$(ini values "$section:$mname")
88
-        done
102
+    local bltndata="$MKIT_LOCAL/data/MKIT_BUILTIN"
103
+    local usrdata="$MKIT_LOCAL/data/macros"
104
+    test -d "$bltndata" && MacroDirs+=("$bltndata")
105
+    test -d "$usrdata" && MacroDirs+=("$usrdata")
106
+    for extra in "$@"; do
107
+        mdir="$MKIT_LOCAL/data/${extra//:/.}"
108
+        test -d "$mdir" || continue
109
+        MacroDirs+=("$mdir")
89 110
     done
90
-    debug_var MacroMap
91 111
     while IFS= read -r line; do
92 112
         __expand_line "$line"
93 113
     done
94 114
 }
95 115
 
96
-__guess_ftype() {
97
-    #
98
-    # Guess file type from destination path $1
99
-    #
100
-    local dstpath=$1    # destination path
101
-    case $dstpath in
102
-        *)    echo MKIT_COMMON ;;
103
-    esac
104
-}
105
-
106 116
 __qfs() {
107 117
     #
108 118
     # Quote for our sed scipt's RHS
@@ -165,38 +175,139 @@ __rec_built() {
165 175
     echo "1:$file" >> "$MKIT_LOCAL/built.lst"
166 176
 }
167 177
 
168
-_mkit_data() {
178
+__rec_builtr() {
169 179
     #
170
-    # Build sampler showing all macro values
180
+    # Record dir $1 for recursive  deletion on `clean`
181
+    #
182
+    local path=$1
183
+    mkdir -p "$MKIT_LOCAL"
184
+    echo "r:$path" >> "$MKIT_LOCAL/built.lst"
185
+}
186
+
187
+_mkit_builddata() {
188
+    #
189
+    # Build config data
171 190
     #
172 191
     local macro
173 192
     local section
174
-    local sections
175
-    sections=()
176
-    ini lskeys macros | grep -q . && sections=(macros)
177
-    sections+=( $(ini lssect | grep ':macros$') )
178
-    {
179
-        echo "(builtin):"
180
-        echo "  x_MKIT_MKIT_VERSION__ => '__MKIT_MKIT_VERSION__'"
181
-        echo "  x_MKIT_PROJ_NAME__ => '__MKIT_PROJ_NAME__'"
182
-        echo "  x_MKIT_PROJ_CODENAME__ => '__MKIT_PROJ_CODENAME__'"
183
-        echo "  x_MKIT_PROJ_LICENSE__ => '__MKIT_PROJ_LICENSE__'"
184
-        echo "  x_MKIT_PROJ_PKGNAME__ => '__MKIT_PROJ_PKGNAME__'"
185
-        echo "  x_MKIT_PROJ_TAGLINE__ => '__MKIT_PROJ_TAGLINE__'"
186
-        echo "  x_MKIT_PROJ_MAINTAINER__ => '__MKIT_PROJ_MAINTAINER__'"
187
-        echo "  x_MKIT_PROJ_VCS_BROWSER__ => '__MKIT_PROJ_VCS_BROWSER__'"
188
-        echo "  x_MKIT_PROJ_GIT_LASTHASH__ => '__MKIT_PROJ_GIT_LASTHASH__'"
189
-        echo "  x_MKIT_PROJ_GIT_LASTSUMMARY__ => '__MKIT_PROJ_GIT_LASTSUMMARY__'"
190
-        echo "  x_MKIT_PROJ_VERSION__ => '__MKIT_PROJ_VERSION__'"
191
-        for section in "${sections[@]}"; do
192
-            echo "$section:"
193
-            for macro in $(ini lskeys "$section"); do
194
-                echo "  x${macro:1} => '$macro'"
195
-            done
193
+    test -d "$MKIT_LOCAL/data/build.macros" && {
194
+        warn "mkit: using cached _mkit_builddata: $(date -Isec -r "$MKIT_LOCAL/data/build.macros")"
195
+        warn "mkit:   (hint: run 'make clean' to regenerate it)"
196
+        return 0
197
+    }
198
+    __rec_builtr "$MKIT_LOCAL/data"
199
+    for macro in $(ini lskeys "build:macros"); do
200
+        ini values "build:macros:$macro" | __macrow "build:macros/$macro"
201
+    done
202
+}
203
+
204
+_mkit_inidata() {
205
+    #
206
+    # Build INI data
207
+    #
208
+    test -d "$MKIT_LOCAL/data/ini" && {
209
+        warn "mkit: using cached _mkit_inidata: $(date -Isec -r "$MKIT_LOCAL/data/ini")"
210
+        warn "mkit:   (hint: run 'make clean' to regenerate it)"
211
+        return 0
212
+    }
213
+    __rec_builtr "$MKIT_LOCAL/data"
214
+    local sect
215
+    local key
216
+    ini lssect \
217
+      | while read -r sect; do
218
+            mkdir -p "$MKIT_LOCAL/data/ini/$sect"
219
+            ini lskeys "$sect" \
220
+              | while read -r key; do
221
+                    ini values "$sect:$key" >"$MKIT_LOCAL/data/ini/$sect/$key"
222
+                done
196 223
         done
197
-    } \
198
-      | __expand_macros "MKIT_BUILTIN" "${sections[@]}" \
199
-      | sed '/^  x/ s|x|_|'
224
+}
225
+
226
+_mkit_metadata() {
227
+    #
228
+    # Build meta data
229
+    #
230
+    test -d "$MKIT_LOCAL/data/MKIT_BUILTIN" && {
231
+        warn "mkit: using cached _mkit_metadata: $(date -Isec -r "$MKIT_LOCAL/data/MKIT_BUILTIN")"
232
+        warn "mkit:   (hint: run 'make clean' to regenerate it)"
233
+        return 0
234
+    }
235
+    __rec_builtr "$MKIT_LOCAL/data"
236
+    echo "$MKIT_VERSION"            | __macrow MKIT_BUILTIN/__MKIT_MKIT_VERSION__
237
+    ini 1value project:name         | __macrow MKIT_BUILTIN/__MKIT_PROJ_NAME__
238
+    ini 1value project:codename     | __macrow MKIT_BUILTIN/__MKIT_PROJ_CODENAME__
239
+    ini 1value project:license      | __macrow MKIT_BUILTIN/__MKIT_PROJ_LICENSE__
240
+    ini 1value project:pkgname      | __macrow MKIT_BUILTIN/__MKIT_PROJ_PKGNAME__
241
+    ini 1value project:tagline      | __macrow MKIT_BUILTIN/__MKIT_PROJ_TAGLINE__
242
+    ini 1value project:maintainer   | __macrow MKIT_BUILTIN/__MKIT_PROJ_MAINTAINER__
243
+    ini 1value project:vcs_browser  | __macrow MKIT_BUILTIN/__MKIT_PROJ_VCS_BROWSER__
244
+    __cached git_lasthash           | __macrow MKIT_BUILTIN/__MKIT_PROJ_GIT_LASTHASH__
245
+    __cached git_lastsummary        | __macrow MKIT_BUILTIN/__MKIT_PROJ_GIT_LASTSUMMARY__
246
+    __cached semver                 | __macrow MKIT_BUILTIN/__MKIT_PROJ_VERSION__
247
+    for section in macros pystuff:macros debstuff:macros rpmstuff:macros; do
248
+        for macro in $(ini lskeys "$section"); do
249
+            ini values "$section:$macro" | __macrow "$section/$macro"
250
+        done
251
+    done
252
+}
253
+
254
+__subdirs() {
255
+    #
256
+    # List direct sub-directories of $1
257
+    #
258
+    find "$1" -maxdepth 1 -mindepth 1 -printf '%P\n' -type d
259
+}
260
+
261
+__subfiles() {
262
+    #
263
+    # List direct sub-files of $1
264
+    #
265
+    find "$1" -maxdepth 1 -mindepth 1 -printf '%P\n' -type f
266
+}
267
+
268
+_mkit_data() {
269
+    #
270
+    # Build sampler showing all macro values
271
+    #
272
+    warn "DEPRECATION: _mkit_data is deprecated and will be removed soon!"
273
+    warn "DEPRECATION: Use _mkit_show_metadata or _mkit_show_build instead."
274
+    warn "DEPRECATION: (redirecting to _mkit_show_metadata)"
275
+    _mkit_show_metadata
276
+}
277
+
278
+_mkit_show_metadata() {
279
+    #
280
+    # Show sampler of macro values
281
+    #
282
+    __show_msection MKIT_BUILTIN
283
+    __show_msection macros
284
+    __show_msection rpmstuff:macros
285
+    __show_msection debstuff:macros
286
+    __show_msection pystuff:macros
287
+}
288
+
289
+_mkit_show_builddata() {
290
+    #
291
+    # Show sampler of config values
292
+    #
293
+    __show_msection build:macros
294
+}
295
+
296
+__show_msection() {
297
+    #
298
+    # Show macros of section $1
299
+    #
300
+    local section=$1
301
+    local mname
302
+    local first=true
303
+    local label=$section
304
+    local secdir="$MKIT_LOCAL/data/${section//:/.}"
305
+    test -d "$secdir" || return 0
306
+    test "$section" == MKIT_BUILTIN && label="(builtin)"
307
+    for mname in $(__subfiles "$secdir"); do
308
+        $first && echo "$label:"; first=false
309
+        echo "    $mname => '$(<"$secdir/$mname")'"
310
+    done
200 311
 }
201 312
 
202 313
 build() {
@@ -271,7 +382,7 @@ debstuff() {
271 382
             mkdir -p "$(dirname "$dftgt")"
272 383
             __build1 "$dfsrc" "$dftgt" debstuff
273 384
         done
274
-    __rec_built debian
385
+    __rec_builtr debian
275 386
 }
276 387
 
277 388
 dist() {
@@ -292,6 +403,7 @@ dist() {
292 403
     mkdir -p "$dirname/.mkit"
293 404
     echo -n "$version" > "$dirname/.mkit/semver"
294 405
     echo -n "$git_lasthash" > "$dirname/.mkit/git_lasthash"
406
+    cp -r "$MKIT_LOCAL/data" "$dirname/.mkit/"
295 407
     tar -cf "$dirname.tar" "$dirname"
296 408
     gzip -f "$dirname.tar"      # see above FIXME
297 409
     __rec_built "$dirname.tar.gz"
@@ -309,3 +421,17 @@ rpmstuff() {
309 421
     test -f "$specsrc" || die "specfile template not found: $specsrc"
310 422
     __build1 "$specsrc" "$specname" rpmstuff
311 423
 }
424
+
425
+build_pystuff() {
426
+    #
427
+    # Build setup.py
428
+    #
429
+    local skel  # source of specfile
430
+    skel="$(ini 1value "dist:pystuff")"
431
+    test -n "$skel" || die "dist:pystuff not specified"
432
+    test -f "$skel" || die "setup.py template not found: $skel"
433
+    __build1 "$skel" "setup.py" pystuff
434
+    python setup.py sdist
435
+    __rec_builtr dist
436
+    __rec_built MANIFEST
437
+}

+ 44
- 22
utils/mkit/include/facts.sh View File

@@ -20,6 +20,13 @@ git_bool() {
20 20
         dirty)
21 21
             git_bool dirty_files || git_bool dirty_index
22 22
             ;;
23
+        async)
24
+            local status_desc   # status description (in square brackets)
25
+            status_desc=$(git status -sb | grep '^##.*' | grep -o '\[[^]]*\]$')
26
+            grep -qw behind <<<"$status_desc" && return 0
27
+            grep -qw ahead <<<"$status_desc" && return 0
28
+            return 1
29
+            ;;
23 30
         *)
24 31
             warn "unknown git bool asked: $bool_name"
25 32
             return 2
@@ -124,6 +131,42 @@ git_lastsummary() {
124 131
       | cut -d' ' -f2-
125 132
 }
126 133
 
134
+make_bmeta() {
135
+    #
136
+    # Compose build metadata string
137
+    #
138
+    local is_tagged=T   # T if tagged (clean, no metadata), F if devel
139
+    local brname        # current branch name
140
+    local ghash         # current commit short hash
141
+    if ! git describe --tags --exact-match HEAD >&/dev/null;
142
+    then    # we are at a later commit than the last tag
143
+        is_tagged=F
144
+        brname=$(git_fact current_branch | sed 's/[^[:alnum:]]/_/g')
145
+        ghash=$(git_fact latest_sha)
146
+    fi
147
+    {
148
+        if test "$is_tagged" == F; then
149
+            test -n "$stamp" && echo "t$stamp"
150
+            echo "$brname"
151
+            echo "g$ghash"
152
+            test -n "$MKIT_UPSTREAM" && echo "u$MKIT_UPSTREAM"
153
+            git_bool async && "$MKIT_ASYNC" && echo async
154
+            "$MKIT_IN_CI" && test -z "$MKIT_UPSTREAM" && git_bool async && {
155
+                warn "branch is out-of sync with upstream; git hash might be misleading"
156
+                warn "  (hint: if this is due to CI auto-rebase, set MKIT_UPSTREAM to original shorthash)"
157
+            }
158
+        fi
159
+        git_bool dirty && echo dirty
160
+    } | paste -sd.
161
+}
162
+
163
+make_suffix() {
164
+    local bmeta
165
+    bmeta=$(make_bmeta)
166
+    test -n "$bmeta" || return 0
167
+    echo "+$bmeta"
168
+}
169
+
127 170
 semver() {
128 171
     #
129 172
     # Build proper SemVer version string
@@ -162,10 +205,6 @@ semver() {
162 205
     local xyz           # base version string
163 206
     local prerl         # pre-release keyword (from mkit.ini, eg. 'beta')
164 207
     local latest_tag    # latest git tag
165
-    local brname        # current branch name
166
-    local ghash         # current commit short hash
167
-    local is_tagged=T   # T if tagged (clean, no metadata), F if devel
168
-    local is_dirty=F    # F if dirty, T if clean
169 208
     local stamp         # timestamp or nothing (see $MKIT_TSTAMP)
170 209
     local suffix        # version suffix
171 210
     prerl=$(ini 1value project:prerl)
@@ -189,24 +228,7 @@ semver() {
189 228
         *)  warn "bad form of last tag, using base version from mkit.ini: tag is '$latest_tag'"
190 229
             xyz=$(ini 1value project:version) ;;
191 230
     esac
192
-    if ! git describe --tags --exact-match HEAD >&/dev/null;
193
-    then    # we are at a later commit than the last tag
194
-        is_tagged=F
195
-        brname=$(git_fact current_branch | sed 's/[^[:alnum:]]/_/g')
196
-        ghash=$(git_fact latest_sha)
197
-    fi
198
-    git_bool dirty && is_dirty=T
199
-    case "$is_dirty:$is_tagged:$stamp" in
200
-        F:T:*)  suffix=""                                 ;;
201
-        T:T:)   suffix="+dirty"                           ;;
202
-        T:T:*)  suffix="+t$stamp.dirty"                   ;;
203
-        F:F:)   suffix="+$brname.g$ghash"                 ;;
204
-        F:F:*)  suffix="+t$stamp.$brname.g$ghash"         ;;
205
-        T:F:)   suffix="+$brname.g$ghash.dirty"           ;;
206
-        T:F:*)  suffix="+t$stamp.$brname.g$ghash.dirty"   ;;
207
-        *)      suffix=MKIT_BUG
208
-                warn "MKIT_BUG: bad dirt/commit detection" ;;
209
-    esac
231
+    suffix=$(make_suffix)
210 232
     test -n "$prerl" && suffix="-$prerl$suffix"
211 233
     echo "$xyz$suffix"
212 234
 }

+ 77
- 16
utils/mkit/include/mkit.sh View File

@@ -34,8 +34,14 @@ __valid_targets() {
34 34
     #
35 35
     # List valid routes
36 36
     #
37
+    echo _mkit_builddata
37 38
     echo _mkit_data
39
+    echo _mkit_inidata
40
+    echo _mkit_metadata
41
+    echo _mkit_show_builddata
42
+    echo _mkit_show_metadata
38 43
     echo build
44
+    echo build_pystuff
39 45
     echo clean
40 46
     echo debstuff
41 47
     echo dist
@@ -80,27 +86,82 @@ __compver() {
80 86
     #
81 87
     # True if version $1 matches our version
82 88
     #
83
-    # If our x is 0, check first two fragments, otherwise check just
84
-    # the x.  Fragments must equal.
89
+    # We're following a particular convention described in SemVer
90
+    # issue #363:
91
+    #
92
+    #     https://github.com/semver/semver/issues/363
93
+    #
94
+    # In short: If our X is 0, check first two fragments, otherwise
95
+    # check just the x.  Fragments must equal.
85 96
     #
86 97
     local their_ver=$1      # their version
87 98
     local our_x             # our X
88 99
     local our_y             # our Y
100
+    local our_z             # our z
89 101
     local their_x           # their X
90 102
     local their_y           # their Y
91
-    their_x=${their_ver%%.*}
92
-    their_y=${their_ver##$their_x.}
93
-    their_y=${their_y%%.*}
94
-    our_x=${MKIT_VERSION%%.*}
95
-    our_y=${MKIT_VERSION##$our_x.}
96
-    our_y=${our_y%%.*}
97
-    debug_var MKIT_VERSION our_x our_y their_ver their_x their_y
98
-    test "$their_x" -eq "$our_x" || return 1
99
-    test "$our_x" -eq 0 && {
100
-        test "$their_y" = "$our_y"
101
-        return $?
103
+    local their_z           # their Z
104
+    local diff_x='='        # difference in X: '=' for equal, 'o' for different
105
+    local diff_y='='        #  ^^ ...... in Y
106
+    local diff_z='='        #  ^^ ...... in Z
107
+    read -r their_x their_y their_z <<<"$(__parse_ver_xyz "$their_ver")" || die
108
+    read -r our_x   our_y   our_z   <<<"$(__parse_ver_xyz "$MKIT_VERSION")" || die
109
+    test "$their_x" -eq "$our_x" || diff_x=o
110
+    test "$their_y" -eq "$our_y" || diff_y=o
111
+    test "$their_z" -eq "$our_z" || diff_z=o
112
+    debug_var MKIT_VERSION our_x our_y our_z their_ver their_x their_y their_z diff_x diff_y diff_z
113
+    case $our_x.$our_y:$diff_x.$diff_y.$diff_z in
114
+        *.*:=.=.=)  return 0 ;;
115
+        *.*:o.?.?)  return 1 ;;
116
+        0.0:=.=.o)  __compver_hint_async ;;
117
+        0.*:=.=.?)  __compver_hint_async ;;
118
+        0.*:=.o.?)  return 1 ;;
119
+        *.*:=.=.o)  __compver_hint_async ;;
120
+        *)          warn "MKit bug while comparing versions!"
121
+                    warn " .. MKit could not handle version difference; here's dump:"
122
+                    warn " ...... MKIT_VERSION=$MKIT_VERSION"
123
+                    warn " ...... their_ver=$their_ver"
124
+                    warn " ...... our_x=$our_x our_y=$our_y our_z=$our_z"
125
+                    warn " ...... their_x=$their_x their_y=$their_y their_z=$their_z"
126
+                    warn " ...... diff_x=$diff_x diff_y=$diff_y diff_z=$diff_z"
127
+                    return 1 ;;
128
+    esac
129
+}
130
+
131
+__parse_ver_xyz() {
132
+    #
133
+    # Print space-separated X, Y and Z from version $1
134
+    #
135
+    local ver=$1
136
+    local xyz
137
+    xyz=$(grep -oE '^[0-9]+[.][0-9]+[.][0-9]+' <<<"$ver")
138
+    test -n "$xyz" || {
139
+        warn "could not parse version: $ver"
102 140
     }
103
-    return 0
141
+    echo "${xyz//./ }"
142
+}
143
+
144
+__compver_hint_async() {
145
+    #
146
+    # Warn about the version being async
147
+    #
148
+    # Versions where later fragments are different are considered
149
+    # compatible, but when MKit is updated, the best practice is
150
+    # to consult the changelog and see if fixes or new features
151
+    # enable optimizing or removing workarounds from the mkit.ini
152
+    # file.
153
+    #
154
+    # For that reason we will inform the maintainer about this
155
+    # fact.
156
+    #
157
+    # Because in typical MKit usage the MKit itself is embedded
158
+    # in the same git repository as the file, it should be easy
159
+    # to maintain the synchronicity.
160
+    #
161
+    warn "hint: mkit.ini version is out of sync: MKit: $MKIT_VERSION, mkit.ini: $their_ver"
162
+    warn "hint:  .. To hide this hint, consider updating mkit.ini based"
163
+    warn "hint:  .. on changes between these versions and update version"
164
+    warn "hint:  .. directive (\`#mkit version=..\`) to match MKit."
104 165
 }
105 166
 
106 167
 __chkiniversion() {
@@ -116,10 +177,10 @@ __chkiniversion() {
116 177
         {
117 178
             head -3 "$MKIT_INI"
118 179
             tail -3 "$MKIT_INI"
119
-        } | grep -m 1 -E '^# *mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
180
+        } | grep -m 1 -E '^#mkit +version *= *v?[0-9]+\.[0-9]+\.[0-9]+'
120 181
     )
121 182
     test -n "$ver_line" \
122
-     || die "version mark ('#mkit version=x.y.z') not found in: $MKIT_INI"
183
+     || die "version directive ('#mkit version=x.y.z') not found in: $MKIT_INI"
123 184
     their_ver="$(tr -d '[:blank:]v' <<<"${ver_line##*=}")"
124 185
     __compver "$their_ver" \
125 186
      || die "bad mkit.ini version: $their_ver does not match $MKIT_VERSION"

+ 64
- 1
utils/mkit/include/vars.sh View File

@@ -4,6 +4,20 @@
4 4
 # See LICENSE file for copyright and license details.
5 5
 
6 6
 
7
+#
8
+# Add 'async' tag to build meta-data (true|false)
9
+#
10
+# If 'true' and during the version computation git branch is behind
11
+# or ahead its remote counterpart, build meta-data (part after '+'
12
+# sign) will contain word 'async'.
13
+#
14
+# This is to warn testers and developers when build was done after
15
+# automatic rebase done by CI system.
16
+#
17
+# Defaults to 'true'.
18
+#
19
+MKIT_ASYNC=${MKIT_ASYNC:-true}
20
+
7 21
 #
8 22
 # Bump size (for vbump_? and release_?)
9 23
 #
@@ -26,6 +40,16 @@ MKIT_DEFAULT_MODE="644"
26 40
 #
27 41
 MKIT_DRY=${MKIT_DRY:-false}
28 42
 
43
+#
44
+# Is MKit running in CI (true|false)
45
+#
46
+# If MKit is running in CI, it's recommended to set this to 'true'
47
+# to enable one or more useful warnings.
48
+#
49
+# Defaults to 'false'.
50
+#
51
+MKIT_IN_CI=${MKIT_IN_CI:-false}
52
+
29 53
 #
30 54
 # Path to mkit.ini
31 55
 #
@@ -83,7 +107,46 @@ MKIT_PROJ_PKGNAME=""
83 107
 #
84 108
 MKIT_TSTAMP=${MKIT_TSTAMP:-ctime}
85 109
 
110
+#
111
+# Upstream hash to add to build meta-data
112
+#
113
+# If set to non-empty string, it must represent a short-hash of
114
+# upstream commit on which local branch was automatically rebased
115
+# before build.
116
+#
117
+# If CI system automatically rebases branches, the resulting short-hash
118
+# (appearing with `g` prefix) will be meaningless, and might be
119
+# misleading -- testers and developers might see the build as coming
120
+# from an unknown source.
121
+#
122
+# In that case, it's strongly recommended for CI to set this to the
123
+# original pushed short-hash before the rebase.  Resulting meta-data
124
+# will contain both hashes, allowing users to pair test results with
125
+# original push.  The appearance of the extra hash will also warn
126
+# about the fact that the rebase took place.
127
+#
128
+# For example, if developer pushed branch 'foo' that pointed to
129
+# `5faf551`, and CI system rebased it, altering the HEAD to
130
+# `bb4baa4`, by default the version would look like:
131
+#
132
+#     0.0.1+t202103011224.foo.gbb4baa4
133
+#
134
+# This would be meaningless for testing, as the `bb4baa4` hash is
135
+# completely temporary and unknonwn.
136
+#
137
+# However, a conformant CI should set `MKIT_UPSTREAM=5faf551`, which
138
+# will result in version like:
139
+#
140
+#     0.0.1+t202103011224.foo.gbb4baa4.u5faf551
141
+#
142
+# which still has technically correct git hash after `g`, but contains
143
+# the original hash as pushed after `u`.
144
+#
145
+# Defaults to empty value.
146
+#
147
+MKIT_UPSTREAM=${MKIT_UPSTREAM:-}
148
+
86 149
 #
87 150
 # This MKit version
88 151
 #
89
-MKIT_VERSION=0.0.40
152
+MKIT_VERSION=0.0.56

+ 25
- 10
utils/mkit/make View File

@@ -20,15 +20,30 @@ init_core() {
20 20
 #
21 21
 MKIT_DIR=${MKIT_DIR:-$(dirname "$0")}
22 22
 
23
+just_ini() {
24
+    #
25
+    # Just do one mkit.ini operation $1
26
+    #
27
+    local op=$1
28
+    local key=$2
29
+    mkit_init || return $?
30
+    ini "$op" "$key"
31
+}
23 32
 
24
-init_core
25
-
26
-case "$1" in
27
-    -V|--version-semver)    echo "$MKIT_VERSION"; exit 0 ;;
28
-    --version)              echo "Mkit (Simple Makefile target helper) $MKIT_VERSION"
29
-                            exit 0 ;;
30
-esac
31
-
32
-mkit_init
33
+main () {
34
+    init_core
35
+    case "$1" in
36
+        -V|--version-semver)    echo "$MKIT_VERSION"; exit 0 ;;
37
+        -i|--ini-1value)        just_ini 1value "$2"; exit $? ;;
38
+        -I|--ini-values)        just_ini values "$2"; exit $? ;;
39
+        --ini-lskeys)           just_ini lskeys "$2"; exit $? ;;
40
+        --ini-lssect)           just_ini lssect "$2"; exit $? ;;
41
+        --ini-sec)              just_ini sec    "$2"; exit $? ;;
42
+        --version)              echo "Mkit (Simple Makefile target helper) $MKIT_VERSION"
43
+                                exit 0 ;;
44
+    esac
45
+    mkit_init
46
+    route "$@"
47
+}
33 48
 
34
-route "$@"
49
+main "$@"

+ 23
- 4
utils/mkit/mkit.mk View File

@@ -5,10 +5,26 @@ export MKIT_DIR
5 5
 
6 6
 all: build
7 7
 
8
-_mkit_data:
8
+_mkit_builddata: _mkit_metadata
9
+	@"$(MKIT_DIR)"/make _mkit_builddata
10
+
11
+_mkit_data: _mkit_metadata _mkit_builddata
9 12
 	@"$(MKIT_DIR)"/make _mkit_data
13
+	@"$(MKIT_DIR)"/make clean
14
+
15
+_mkit_inidata:
16
+	@"$(MKIT_DIR)"/make _mkit_inidata
17
+
18
+_mkit_metadata:
19
+	@"$(MKIT_DIR)"/make _mkit_metadata
10 20
 
11
-build:
21
+_mkit_show_metadata: _mkit_metadata
22
+	@"$(MKIT_DIR)"/make _mkit_show_metadata
23
+
24
+_mkit_show_builddata: _mkit_builddata
25
+	@"$(MKIT_DIR)"/make _mkit_show_builddata
26
+
27
+build: _mkit_builddata
12 28
 	@"$(MKIT_DIR)"/make build
13 29
 
14 30
 clean:
@@ -17,9 +33,12 @@ clean:
17 33
 debstuff: dist
18 34
 	@"$(MKIT_DIR)"/make debstuff
19 35
 
20
-dist: clean
36
+dist: clean _mkit_metadata
21 37
 	@"$(MKIT_DIR)"/make dist
22 38
 
39
+build_pystuff: clean _mkit_metadata build
40
+	@"$(MKIT_DIR)"/make build_pystuff
41
+
23 42
 rpmstuff: dist
24 43
 	@"$(MKIT_DIR)"/make rpmstuff
25 44
 
@@ -53,4 +72,4 @@ vbump_y:
53 72
 vbump_z:
54 73
 	@"$(MKIT_DIR)"/make vbump_z
55 74
 
56
-.PHONY: all _mkit_data clean dist rpmstuff install uninstall release release_x release_y release_z vbump vbump_x vbump_y vbump_z
75
+.PHONY: all _mkit_builddata _mkit_data _mkit_inidata _mkit_metadata _mkit_show_builddata _mkit_show_metadata build_pystuff clean dist rpmstuff install uninstall release release_x release_y release_z vbump vbump_x vbump_y vbump_z

+ 174
- 14
utils/mkit/stub View File

@@ -63,6 +63,153 @@ deploy() {
63 63
             else
64 64
                 echo "(Nothing to say about this project.)"
65 65
             fi
66
+            echo ""
67
+            echo "See MAINTAINERS.md for instructions how to build and"
68
+            echo "maintain this MKit project."
69
+            ;;
70
+
71
+        MAINTAINERS.md)
72
+            local heading="$any_name - maintainer instructions"
73
+            echo "${heading^^}"
74
+            tr -c '=\n' '=' <<<"$heading"
75
+            echo ''
76
+            echo "<!--"
77
+            echo "    Note: This file has been auto-generated by MKit"
78
+            echo "    v$MKIT_VERSION when initializing the project."
79
+            echo "-->"
80
+            echo ''
81
+            echo "This project is using MKit for packaging and versioning"
82
+            echo "meta-data; this file describes how to do basic maintenance"
83
+            echo "operations."
84
+            echo ''
85
+            echo "MKit uses GNU Make as an interface, so all operations are"
86
+            echo "'make' targets and GNU Make takes care of the dependencies"
87
+            echo "between them.  For example, to install the project it's enough"
88
+            echo "to call 'make install'; GNU Make will call 'make built'"
89
+            echo "automatically if needed."
90
+            echo ""
91
+            echo ""
92
+            echo "Variables"
93
+            echo "---------"
94
+            echo ""
95
+            echo " *  \`DESTDIR\` - root of the installation destination"
96
+            echo " *  \`PREFIX\` - deployment prefix (often \`/usr\` or"
97
+            echo "    \`/usr/local\`)"
98
+            echo " *  \`MKIT_DRY\` - set to \`true\` to prevent MKit from making"
99
+            echo "    any changes"
100
+            echo " *  \`MKIT_DEBUG\` - set to \`true\` to have MKit display"
101
+            echo "    (lots of) debugging information"
102
+            echo ""
103
+            echo "See *utils/mkit/include/vars.sh* for full list oof supported"
104
+            echo "variables. (You can use \`sfdoc utils/mkit/include/vars.sh\`"
105
+            echo "if you have sfdoc installed.)"
106
+            echo ""
107
+            echo ""
108
+            echo "Building and installation"
109
+            echo "-------------------------"
110
+            echo ""
111
+            echo "These operations are allowed on any branch.  Assets built from"
112
+            echo "development branches will be marked using distinctive version"
113
+            echo "number containing timestamp, branch name and commit short-hash."
114
+            echo ""
115
+            echo " *  \`make\` - same as \`make build\`"
116
+            echo " *  \`make build\` - build project files"
117
+            echo " *  \`make install\` - install project to \`\$DESTDIR\`"
118
+            echo " *  \`make uninstall\` - uninstall project from \`\$DESTDIR\`"
119
+            echo " *  \`make rpmstuff\` - create RPM SPEC file and a source"
120
+            echo "    tarball"
121
+            echo " *  \`make debstuff\` - create 'debian' directory and a source"
122
+            echo "    tarball"
123
+            echo " *  \`make clean\` - remove any previously built assets".
124
+            echo ""
125
+            echo ""
126
+            echo "Versioning"
127
+            echo "----------"
128
+            echo ""
129
+            echo "These operations are only allowed on *release source branch*:"
130
+            echo ""
131
+            echo " *  \`make vbump\` - bump version and create bump commit"
132
+            echo " *  \`make release\` - create release tag"
133
+            echo ""
134
+            echo ""
135
+            echo "Recommended workflow"
136
+            echo "--------------------"
137
+            echo ""
138
+            echo ""
139
+            echo "### Development and testing ###"
140
+            echo ""
141
+            echo "Any branch can be used to create any kind of asset.  Assets"
142
+            echo "built from development branch will be marked using distinctive"
143
+            echo "version number in all MKit macros."
144
+            echo ""
145
+            echo "Development is done in branches as needed, but one branch"
146
+            echo "(often called *master*, *main* or *trunk*) is designated as"
147
+            echo "**release source** branch.  Only maintainer can push into this"
148
+            echo "branch and this is where maintainer creates the next release."
149
+            echo ""
150
+            echo ""
151
+            echo "### Versioning and releases ###"
152
+            echo ""
153
+            echo "After all development branches are merged and project is"
154
+            echo "considered ready for release, maintainer will create new"
155
+            echo "release.  This consists of three steps (only two of them are"
156
+            echo "assisted by MKit):"
157
+            echo ""
158
+            echo " 1. \`make vbump\` - will auto-edit [project:version] in"
159
+            echo "     mkit.ini and start creating **bump commit**."
160
+            echo ""
161
+            echo "    **Bump commit** is a special commit which consists of:"
162
+            echo ""
163
+            echo "     *  Bump of version in mkit.ini"
164
+            echo "     *  commit message providing rudimentary human"
165
+            echo "        readable summary of changes."
166
+            echo ""
167
+            echo "    \`make vbump\` target will cause bump of the *last*"
168
+            echo "    version fragment (Z, or PATCH in SemVer).  To bump other"
169
+            echo "    fragments, use \`make vbump_y\` or \`make vbump_x\` (MINOR"
170
+            echo "    or MAJOR in SemVer, respectively)."
171
+            echo ""
172
+            echo "    MKit will create a template of the message by scanning"
173
+            echo "    all commits since last release and invoke 'git commit' so"
174
+            echo "    that maintainer is presented with a window editing the"
175
+            echo "    commit message."
176
+            echo ""
177
+            echo "    Maintainer is responsible for finishing the commit message"
178
+            echo "    by:"
179
+            echo ""
180
+            echo "     *  Re-wording and merging the items as needed."
181
+            echo "     *  Adding any details, if needed."
182
+            echo "     *  Removing short hashes and file lists added by MKit"
183
+            echo "        (these are added only to make editing easier)."
184
+            echo ""
185
+            echo "    Once maintainer is happy with *bump commit* message,"
186
+            echo "    they can exit the editor and move on to next step."
187
+            echo ""
188
+            echo " 2. \`make release\` - will check if latest commit on current"
189
+            echo "    branch is a *bump commit*, and if yes, will create"
190
+            echo "    a corresponding **release tag**."
191
+            echo ""
192
+            echo "    **Release tags** are annotated tags (see *git-tag(1)*)"
193
+            echo "    formed by version number prefixed by letter \`v\` and are"
194
+            echo "    used by MKit to calculate version number when building"
195
+            echo "    assets.  Release tags contain the *bump commit* message"
196
+            echo "    as the annotation."
197
+            echo ""
198
+            echo "    If a *release destination* branch is specified as"
199
+            echo "    [project:reldst] in mkit.ini, MKit will also update that"
200
+            echo "    branch so that it points to the same commmit as the"
201
+            echo "    newly created release tag."
202
+            echo ""
203
+            echo " 3. Maintainer will push branches and commits to any shared"
204
+            echo "    remotes as needed."
205
+            echo ""
206
+            echo "    Warning: This is your last chance to fix any mistakes."
207
+            echo "    git tags are designed to be permanent, \"official\","
208
+            echo "    write-only objects and they will typically quickly spread"
209
+            echo "    to other clones.  *Don't count on getting rid of release"
210
+            echo "    tag*."
211
+            echo ""
212
+
66 213
             ;;
67 214
 
68 215
         */mkit.ini|mkit.ini)
@@ -90,6 +237,7 @@ deploy() {
90 237
                 echo "[dist]"
91 238
                 {
92 239
                     $MkLicense  && echo "tarball = LICENSE.md"
240
+                    $MkReadme   && echo "tarball = MAINTAINERS.md"
93 241
                     $MkMakefile && echo "tarball = Makefile"
94 242
                     $MkReadme   && echo "tarball = README.md"
95 243
                     echo "tarball = mkit.ini"
@@ -115,6 +263,9 @@ deploy() {
115 263
                 echo "[macros]"
116 264
                 {
117 265
                     echo "__${PackageName^^}_FOO__ = Barr.."
266
+                    echo "    __PROJECT_DESC_MAIN__ = MKIT_STUB_DESCRIPTION - replace this with your project"
267
+                    echo "    __PROJECT_DESC_MAIN__ = MKIT_STUB_DESCRIPTION .. description; this will appear"
268
+                    echo "    __PROJECT_DESC_MAIN__ = MKIT_STUB_DESCRIPTION .. in places like rpm -i"
118 269
                 } | reformat_section
119 270
                 echo ""
120 271
                 echo "[modes]"
@@ -135,18 +286,19 @@ deploy() {
135 286
             ;;
136 287
 
137 288
         packaging/template.spec)
138
-            echo 'Name:       __MKIT_PROJ_PKGNAME__'
139
-            echo 'Version:    __MKIT_PROJ_VERSION__'
140
-            echo 'Release:    1%{?dist}'
141
-            echo 'Summary:    __MKIT_PROJ_NAME__ - __MKIT_PROJ_TAGLINE__'
289
+            echo 'Name:           __MKIT_PROJ_PKGNAME__'
290
+            echo 'Version:        __MKIT_PROJ_VERSION__'
291
+            echo 'Release:        1%{?dist}'
292
+            echo 'Summary:        __MKIT_PROJ_NAME__ - __MKIT_PROJ_TAGLINE__'
142 293
             test -n "$VcsBrowser" && echo 'URL:        __MKIT_PROJ_VCS_BROWSER__'
143
-            $MkLicense && echo "License:    $License"
144
-            echo 'Source0:    %{name}-%{version}.tar.gz'
145
-            echo 'BuildArch:  noarch'
294
+            $MkLicense && echo "License:        $License"
295
+            echo 'Source0:        %{name}-%{version}.tar.gz'
296
+            echo 'BuildArch:      noarch'
297
+            echo 'BuildRequires:  make'
146 298
             echo ''
147 299
             echo 'Requires: MKIT_STUB_REQUIRES'
148 300
             echo '%description'
149
-            echo 'MKIT_STUB_DESCRIPTION'
301
+            echo '__PROJECT_DESC_MAIN__'
150 302
             echo ''
151 303
             echo '%prep'
152 304
             echo '%setup -q'
@@ -163,6 +315,7 @@ deploy() {
163 315
             echo '%changelog'
164 316
             echo ''
165 317
             echo '# specfile built with MKit __MKIT_MKIT_VERSION__'
318
+            echo "#  .. based on stub from: $MKIT_VERSION"
166 319
             ;;
167 320
 
168 321
         packaging/debian/copyright)
@@ -178,14 +331,16 @@ deploy() {
178 331
             echo 'Standards-Version: 3.9.2'
179 332
             echo 'Build-Depends:'
180 333
             echo ' debhelper (>= 9),'
334
+            echo ' make,'
181 335
             echo ''
182 336
             echo 'Package: __MKIT_PROJ_PKGNAME__'
183 337
             echo 'Architecture: all'
184 338
             echo 'Depends: MKIT_STUB_REQUIRES'
185 339
             echo 'Description: __MKIT_PROJ_NAME__ - __MKIT_PROJ_TAGLINE__'
186
-            echo ' MKIT_STUB_DESCRIPTION'
340
+            echo ' __PROJECT_DESC_MAIN__'
187 341
             echo ''
188 342
             echo '# control file built with MKit __MKIT_MKIT_VERSION__'
343
+            echo "#  .. based on stub from: $MKIT_VERSION"
189 344
             ;;
190 345
 
191 346
         packaging/debian/changelog)
@@ -205,11 +360,11 @@ deploy() {
205 360
             echo ''
206 361
             echo '%:'
207 362
             echo ''
208
-            echo '	dh $@'
363
+            echo '	PREFIX=/usr dh $@'
209 364
             echo ''
210 365
             echo 'override_dh_auto_install:'
211 366
             echo ''
212
-            echo '	make install PREFIX=/usr DESTDIR=debian/tmp'
367
+            echo '	make install DESTDIR=debian/tmp'
213 368
             ;;
214 369
 
215 370
         packaging/debian/source/format)
@@ -430,11 +585,15 @@ deploy() {
430 585
             if $MkReadme; then
431 586
             echo ""
432 587
             echo ""
433
-            echo "README.md"
434
-            echo "---------"
588
+            echo "README.md and MAINTAINERS.md"
589
+            echo "----------------------------"
435 590
             echo ""
436 591
             echo "Each serious project needs a serious README.  Which is why"
437 592
             echo "*stub* has created a 'stub' of one for you."
593
+            echo ""
594
+            echo "Furthermore MAINTAINERS.md is created to help maintainers"
595
+            echo "do basic MKit operations such as building assets and making"
596
+            echo "releases."
438 597
             fi
439 598
 
440 599
             echo ""
@@ -479,7 +638,7 @@ usage() {
479 638
         echo "    -V VERSION    initial version (default: 0.0.0)"
480 639
         echo "    -a            enable autoclean ('make clean' after"
481 640
         echo "                  each 'make install')"
482
-        echo "    -g            make git commits before and adter"
641
+        echo "    -g            make git commits before and after"
483 642
         echo "                  (implies -y)"
484 643
         echo "    -y            don't ask, just do it"
485 644
         echo "    -R            skip creating README.md"
@@ -699,6 +858,7 @@ main() {
699 858
     deploy src/"$PackageName".skel
700 859
     $MkMakefile     && deploy Makefile
701 860
     $MkReadme       && deploy README.md
861
+    $MkReadme       && deploy MAINTAINERS.md
702 862
     $MkLicense      && deploy LICENSE.md
703 863
     $AutoClean      && deploy .mkit/autoclean
704 864
     $MkPackaging    && deploy_packaging