diff options
author | Andreas Fankhauser hiddenalpha.ch | 2024-05-12 12:55:07 +0200 |
---|---|---|
committer | Andreas Fankhauser hiddenalpha.ch | 2024-05-12 12:55:07 +0200 |
commit | 5cc4c2b95df9bf6998d92496ca0e0064314fba39 (patch) | |
tree | ac7d979f81a86703508ff23e2694a6b4d6bfe4d5 /src/main/lua/git/GitflowChangelogGen.lua | |
parent | 1dc9f8c9db499a326ceee6cb3b48878ee17ff9fa (diff) | |
parent | 95d934e8e3918832c03f05b2fc32cb5d5272cb83 (diff) | |
download | UnspecifiedGarbage-wip-LatitudeReSetup-20230620.zip UnspecifiedGarbage-wip-LatitudeReSetup-20230620.tar.gz |
Merge remote-tracking branch 'ha-public/master' into wip-LatitudeReSetup-20230620wip-LatitudeReSetup-20230620
Diffstat (limited to 'src/main/lua/git/GitflowChangelogGen.lua')
-rw-r--r-- | src/main/lua/git/GitflowChangelogGen.lua | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/main/lua/git/GitflowChangelogGen.lua b/src/main/lua/git/GitflowChangelogGen.lua new file mode 100644 index 0000000..3b44ac3 --- /dev/null +++ b/src/main/lua/git/GitflowChangelogGen.lua @@ -0,0 +1,195 @@ + +local log = io.stderr +local main + + +function printHelp() + io.stdout:write(" \n" + .." Helper to extract essential data from a gitflow log which potentially\n" + .." is useful to write a CHANGELOG from.\n" + .." \n" + .." Options:\n" + .." \n" + .." --since <date>\n" + .." Ignore commits with this ISO date and older.\n" + .." \n" + .." --remote <str>\n" + .." Name of the git remote to use. Defaults to 'upstream'.\n" + .." \n" + .." --no-fetch\n" + .." Do NOT update refs from remote. Just use what we have local.\n" + .." \n" + ) +end + + +function parseArgs( app ) + local iA = 0 + while true do iA = iA + 1 + local arg = _ENV.arg[iA] + if not arg then + break + elseif arg == "--since" then + iA = iA + 1; arg = _ENV.arg[iA] + if not arg then log:write("EINVAL: --since needs value\n")return end + app.since = arg + elseif arg == "--remote" then + iA = iA + 1; arg = _ENV.arg[iA] + if not arg then log:write("EINVAL: --remote needs value\n")return end + app.remoteName = arg + elseif arg == "--no-fetch" then + app.isFetch = false + elseif arg == "--help" then + app.isHelp = true; return 0 + else + log:write("EINVAL: ".. arg .."\n")return + end + end + if not app.since then log:write("EINVAL: --since missing\n")return end + if not app.remoteName then app.remoteName = "upstream" end + return 0 +end + + +function readCommitHdr( app ) + --log:write("[DEBUG] parse hdr from '".. app.fullHistory:sub(app.fullHistoryRdBeg, app.fullHistoryRdBeg+256) .."...'\n") + local f, t = app.fullHistory:find("^" + .."commit ........................................[^\n]*\n" + .."Merge: [0-9a-z]+ [0-9a-z]+\n" + .."Author: [^\n]+\n" + .."Date: [^\n]+\n" + .."\n" + , app.fullHistoryRdBeg) + if not f then f, t = app.fullHistory:find("^" + .."commit ........................................[^\n]*\n" + .."Author: [^\n]+\n" + .."Date: [^\n]+\n" + .."\n" + , app.fullHistoryRdBeg) end + if not f then + assert(app.fullHistory:len() == app.fullHistoryRdBeg-1, app.fullHistory:len()..", "..app.fullHistoryRdBeg) + app.parseFn = false + return + end + app.commitHdr = assert(app.fullHistory:sub(f, t-1)) + --log:write("hdrBeginsWith '"..(app.commitHdr:sub(1, 32)).."...'\n") + app.fullHistoryRdBeg = t + 1 + --log:write("hdr parsed. rdCursr now points to '".. app.fullHistory:sub(app.fullHistoryRdBeg, app.fullHistoryRdBeg+16) .."...'\n") + app.parseFn = assert(readCommitMsg) +end + + +function readCommitMsg( app ) + local idxOfC = app.fullHistoryRdBeg + local chrPrev = false + while true do idxOfC = idxOfC + 1 + local chr = app.fullHistory:byte(idxOfC) + --log:write("CHR '"..tostring(app.fullHistory:sub(idxOfC, idxOfC)).."'\n") + if (chr == 0x63) and chrPrev == 0x0A then + idxOfC = idxOfC - 1 + break -- LF followed by 'c' (aka 'commit') found + elseif not chr then + idxOfC = idxOfC - 1 + break + else + chrPrev = assert(chr) + end + end + local mtch = app.fullHistory:sub(app.fullHistoryRdBeg, idxOfC - 1) + assert(mtch) + while mtch:byte(mtch:len()) == 0x0A do mtch = mtch:sub(1, -2) end + mtch = mtch:gsub("\n ", "\n"):gsub("^ ", "") + app.commitMsg = mtch + app.fullHistoryRdBeg = idxOfC + 1 + app.parseFn = readCommitHdr + --log:write("msg parsed. rdCursr now points to '".. app.fullHistory:sub(app.fullHistoryRdBeg, app.fullHistoryRdBeg+16) .."...'\n") + table.insert(app.commits, { + hdr = assert(app.commitHdr), + msg = assert(app.commitMsg), + }) +end + + +function run( app ) + local snk = io.stdout + if app.isFetch then + -- Make sure refs are up-to-date + local gitFetch = "git fetch \"".. app.remoteName .."\"" + log:write("[DEBUG] ".. gitFetch .."\n") + local gitFetch = io.popen(gitFetch) + while true do + local buf = gitFetch:read(1<<16) + if not buf then break end + log:write(buf) + end + end + -- Collect input + local git = "git log --date-order --first-parent --decorate --since \"".. app.since.."\"" + .." \"".. app.remoteName .."/master\"" + .." \"".. app.remoteName .."/develop\"" + log:write("[DEBUG] ".. git .."\n") + local git = io.popen(git) + while true do + local buf = git:read(1<<16) + if not buf then break end + --io.stdout:write(buf) + table.insert(app.fullHistory, buf) + end + -- Parse raw commits + app.fullHistory = table.concat(app.fullHistory) + app.parseFn = assert(readCommitHdr) + while app.parseFn do app.parseFn(app) end + -- Prepare output + local prevDate = "0000-00-00" + local version, prevVersion = "v_._._", false + local dateEntry = false + local entries = {} + for k, v in ipairs(app.commits) do + local date = assert(v.hdr:match("\nDate: +([0-9-]+) ")) + local author = assert(v.hdr:match("\nAuthor: +([^\n]+)\n")) + local prNr, short = v.msg:match("Pull request #(%d+): ([^\n]+)\n") + prevVersion = version + _, version = v.hdr:match("^([^\n]+)\n"):match("tag: ([a-z]+)-([^,]+)[,)]") + if not version then version = prevVersion end + + if version ~= prevVersion or not dateEntry then + if dateEntry then table.insert(entries, dateEntry) end + dateEntry = { + txt = date .." - ".. version .."\n\nResolved issues:\n\n" + } + prevDate = date + end + if prNr then + dateEntry.txt = dateEntry.txt .. short .." (PR ".. prNr ..")\n" + else + dateEntry.txt = dateEntry.txt .. v.msg .."\n" + end + end + if dateEntry then table.insert(entries, dateEntry) end + -- output + for k, v in ipairs(entries) do + snk:write("\n\n") + snk:write(v.txt) + snk:write("\n") + end +end + + +function main() + local app = { + since = false, + remoteName = false, + isFetch = true, + fullHistory = {}, + fullHistoryRdBeg = 1, + commits = {}, + parseFn = false, + } + if parseArgs(app) ~= 0 then os.exit(1) end + if app.isHelp then printHelp() return end + run(app) +end + + +main() + |