Browse Source

Rewrite caching and versioning logic

Essential fact.sh functions git_lasthash() and semver() have been updated
so that they explicitly depend on git or fail, ie. forget about the cache.

Previously git_lasthash() would try to use cache or fail, while semver()
would try to use cache or rely on mkit.ini, which in turn had to be hacked
by dist() in order to make git-less targets expand version correctly
(with build data, eg. `0.1.2+ge1f4a77.dirty`).

The old code was guilty of four sins: inconsistency (git_lasthash()
vs. semver()), side effects (semver() would actually write cache),
hidden dependencies (both actually relied on functions from mkit.sh)
and unnecessary complexity (speculative $version use in semver()).

New code remediates all of these by making both functions just do their
job (ie. get data from VCS).  Places that did benefit from the silent
caching are served by __cached() function created for this purpose.
Alois Mahdal 6 years ago
parent
commit
edda9330da
2 changed files with 66 additions and 48 deletions
  1. 22
    5
      src/include/build.sh
  2. 44
    43
      src/include/facts.sh

+ 22
- 5
src/include/build.sh View File

@@ -59,8 +59,8 @@ __expand_tokens() {
59 59
         echo "s|__MKIT_PROJ_TAGLINE__|$(ini 1value project:tagline | __qfs)|g;"
60 60
         echo "s|__MKIT_PROJ_MAINTAINER__|$(ini 1value project:maintainer | __qfs)|g;"
61 61
         echo "s|__MKIT_PROJ_VCS_BROWSER__|$(ini 1value project:vcs_browser | __qfs)|g;"
62
-        echo "s|__MKIT_PROJ_GIT_LASTHASH__|$(git_lasthash | __qfs)|g;"
63
-        echo "s|__MKIT_PROJ_VERSION__|$(semver | __qfs)|g;"
62
+        echo "s|__MKIT_PROJ_GIT_LASTHASH__|$(__cached git_lasthash | __qfs)|g;"
63
+        echo "s|__MKIT_PROJ_VERSION__|$(__cached semver | __qfs)|g;"
64 64
         echo "s|__MKIT_SELF_VERSION__|$MKIT_VERSION|g;"
65 65
     } >> "$script"
66 66
     sed -f "$script" || die "__expand_tokens failed"
@@ -87,6 +87,24 @@ __qfs() {
87 87
     '
88 88
 }
89 89
 
90
+__cached() {
91
+    #
92
+    # Cached value $1 of function $1()
93
+    #
94
+    # In order to support git-less builds, some values might be cached
95
+    # in $MKIT_LOCAL.  This function gets file $1 from that cache (cache
96
+    # hit) or re-creates it (cache miss), but prints its body in either
97
+    # case.
98
+    #
99
+    # The command to re-create file is the same as the key (ie. no
100
+    # arguments).
101
+    #
102
+    local name=$1
103
+    local_get "$name" && return 0
104
+    "$name" | local_putb "$name"
105
+    local_get "$name"
106
+}
107
+
90 108
 _mkit_data() {
91 109
     #
92 110
     # Build sampler showing all token values
@@ -125,7 +143,6 @@ build() {
125 143
     # Add meat to all skeletons
126 144
     #
127 145
     local srcpath   # each source path
128
-    semver >/dev/null
129 146
     find . -type f -name '*.skel' \
130 147
      | while read -r srcpath; do
131 148
            __build1 "$srcpath"
@@ -153,7 +170,7 @@ debstuff() {
153 170
     local debian_skel   # 'debian' folder skeleton
154 171
     local dfsrc         # each source file from ^^
155 172
     local dftgt         # each built packaging file
156
-    version=$(semver)
173
+    version=$(__cached semver)
157 174
 
158 175
     # tarball - we should already have by means of 'dist'
159 176
     #
@@ -192,8 +209,8 @@ dist() {
192 209
     git_lasthash=$(git_lasthash)
193 210
     mkdir -p "$dirname"
194 211
     ini values "dist:tarball" | xargs -I DIST_ITEM cp -R DIST_ITEM "$dirname"
195
-    update_version "$version" "$dirname/mkit.ini"
196 212
     mkdir -p "$dirname/.mkit"
213
+    echo -n "$version" > "$dirname/.mkit/semver"
197 214
     echo -n "$git_lasthash" > "$dirname/.mkit/git_lasthash"
198 215
     tar -cf "$dirname.tar" "$dirname"
199 216
     gzip -f "$dirname.tar"      # see above FIXME

+ 44
- 43
src/include/facts.sh View File

@@ -85,22 +85,19 @@ git_lasthash() {
85 85
     #
86 86
     # Show last commit hash (with .dirty suffix if needed)
87 87
     #
88
-    # If outside git repo, get it from .mkit/git_lasthash, which
89
-    # should have been put there by dist target.  (I.e., this won't
90
-    # work if you got outside the git repo in other way than dist
91
-    # target, but that's actually expected.)
88
+    # We can't do it outside git repo (or without git) but we should
89
+    # not be asked to; targets that don't require git should make use
90
+    # of cache built by dist target.
92 91
     #
93 92
     local last_hash     # last commit hash
94
-    if git_present; then    # we are in git repo
95
-        last_hash=$(git rev-parse HEAD)
96
-        echo -n "$last_hash"
97
-        git_bool dirty && echo -n ".dirty"
98
-    else    # we are outside (eg. distributor's build dir')
99
-        grep . .mkit/git_lasthash || {
100
-            echo UNKNOWN
101
-            warn "malformed source, could not determine git hash"
102
-        }
103
-    fi
93
+    git_present || {
94
+        echo UNKNOWN_HASH
95
+        warn "no git present; could not determine last hash"
96
+        return 3
97
+    }
98
+    last_hash=$(git rev-parse HEAD)
99
+    echo -n "$last_hash"
100
+    git_bool dirty && echo -n ".dirty"
104 101
 }
105 102
 
106 103
 semver() {
@@ -110,13 +107,13 @@ semver() {
110 107
     # Build version string from available info using following
111 108
     # logic:
112 109
     #
113
-    #  1. use project.version (from mkit.ini)
114
-    #  2. if we are in git, override the version with last tag
115
-    #  3. if set, add project:prerl (from mkit.ini) as pre-release ID
110
+    #  1. Use version from last git tag (or mkit.ini if there is no
111
+    #     tag, which is possible on new project)
112
+    #  2. if set, add project:prerl (from mkit.ini) as pre-release ID
116 113
     #     (afer dash)
117
-    #  4. if we are at a later commit than the last tag, add branch
114
+    #  3. if we are at a later commit than the last tag, add branch
118 115
     #     name and commit sha1 to build metadata (after plus sign)
119
-    #  5. if the tree is "dirty", i.e. has uncommited changes,
116
+    #  4. if the tree is "dirty", i.e. has uncommited changes,
120 117
     #     add "dirty" to build metadata
121 118
     #
122 119
     # The version is compatible with SemVer 2.0.0.
@@ -148,37 +145,41 @@ semver() {
148 145
     # FIXME:  Using project:prerl for release IDs may not be compatible with
149 146
     #         release strategy implemented in release.sh
150 147
     #
151
-    local version       # version string (final result)
148
+    local xyz           # base version string
152 149
     local prerl         # pre-release keyword (from mkit.ini, eg. 'alpha')
153 150
     local latest_tag    # latest git tag
154 151
     local commit        # commit indicator (CURRENT_BRANCH.gHASH)
155 152
     local dirty         # 0 if dirty, 1 if clean
156 153
     local suffix        # version suffix
157
-    local_get semver && return 0
158
-    version=$(ini 1value project:version)
159 154
     prerl=$(ini 1value project:prerl)
160 155
     grep ":" <<<"$prerl" \
161 156
      && warn "colon in project:prerl may corrupt version data: $prerl"
162
-    if git_present;
163
-    then    # we are in git repo... so we can get smart
164
-        latest_tag=$(git_fact latest_tag)
165
-        if ! git describe --tags --exact-match HEAD >&/dev/null;
166
-        then    # we are at a later commit than the last tag
167
-            commit="$(git_fact current_branch).g$(git_fact latest_sha)"
168
-        fi
169
-        git_bool dirty; dirty=$?
170
-        test -n "$latest_tag" && version=${latest_tag:1}
171
-        case "$dirty:$commit" in
172
-            1:)  suffix=""               ;;
173
-            0:)  suffix="+dirty"         ;;
174
-            1:*) suffix="+$commit"       ;;
175
-            0:*) suffix="+$commit.dirty" ;;
176
-            *)   suffix=MKIT_BUG
177
-                 warn "MKIT_BUG: bad dirt/commit detection" ;;
178
-        esac
179
-        test -n "$prerl" && suffix="-$prerl$suffix"
180
-        version="$version$suffix"
157
+    git_present || {
158
+        echo UNKNOWN_VERSION
159
+        warn "no git present; could not determine SemVer"
160
+        return 3
161
+    }
162
+    latest_tag=$(git_fact latest_tag)
163
+    case $latest_tag in
164
+        v*) xyz=${latest_tag:1} ;;
165
+        "") warn "no tags, using base version from mkit.ini (ok for new project)"
166
+            xyz=$(ini 1value project:version) ;;
167
+        *)  warn "bad form of last tag, using base version from mkit.ini: tag is '$latest_tag'"
168
+            xyz=$(ini 1value project:version) ;;
169
+    esac
170
+    if ! git describe --tags --exact-match HEAD >&/dev/null;
171
+    then    # we are at a later commit than the last tag
172
+        commit="$(git_fact current_branch).g$(git_fact latest_sha)"
181 173
     fi
182
-    local_putb semver <<<"$version"
183
-    echo "$version"
174
+    git_bool dirty; dirty=$?
175
+    case "$dirty:$commit" in
176
+        1:)  suffix=""               ;;
177
+        0:)  suffix="+dirty"         ;;
178
+        1:*) suffix="+$commit"       ;;
179
+        0:*) suffix="+$commit.dirty" ;;
180
+        *)   suffix=MKIT_BUG
181
+             warn "MKIT_BUG: bad dirt/commit detection" ;;
182
+    esac
183
+    test -n "$prerl" && suffix="-$prerl$suffix"
184
+    echo "$xyz$suffix"
184 185
 }