gitoria
All repositories: gitoria
4.6 KB
// lib/git-helpers.hl — what the git readers look up: path and name checks, ids, tab-separated fields, sizes, and the// commit-subject markers of pull requests (`|||PR`) and releases (`|||RL`). Statics only, git itself is not called here.// a path we let through: printable, no leading dash, no backslash / quote / control charactersstatic safePath = (path) => {if (path == null || path == '' || path.length > 300 || path.startsWith('-')) { return false }let i = 0while (i < path.length) {let c = path.charCodeAt(i)if (c < 32 || c == 127 || c == 34 || c == 92 || c == 58) { return false }i = i + 1}return true}static safeName = (n) => { return safePath(n) && n.length <= 100 && !n.endsWith('/') && !n.includes('//') }// a URL path piece: percent-encoded, the slashes kept (encodeURIComponent is a global since hybriel #14)static enc = (s) => { return encodeURIComponent(s).replaceAll('%2F', '/') }static isHexId = (s) => {if (s == null || s.length < 4 || s.length > 40) { return false }let i = 0while (i < s.length) {let c = s.charCodeAt(i)if (!((c >= 48 && c <= 57) || (c >= 97 && c <= 102))) { return false }i = i + 1}return true}// tab-separated fields of a line git wrote. (split() / indexOf() do not find a tab in a line that// came from hl:proc, so scan by character code.)static tabAt = (line) => {let i = 0while (i < line.length) {if (line.charCodeAt(i) == 9) { return i }i = i + 1}return -1}static tabs = (line) => {let out = []let start = 0let i = 0while (i < line.length) {if (line.charCodeAt(i) == 9) {out.push(line.slice(start, i))start = i + 1}i = i + 1}out.push(line.slice(start))return out}static sizeText = (n) => {if (n < 1024) { return n + ' B' }let unit = n < 1048576 ? 1024 : 1048576let t = (n * 10 - (n * 10) % unit) / unitreturn ((t - t % 10) / 10) + '.' + (t % 10) + (n < 1048576 ? ' KB' : ' MB')}// ---- the markers (pulls.hl, releases.hl) ----------------------------------------------------------// a commit subject → null (not a request) or { target: '' (= default) | name, title }static parsePull = (subject) => {if (subject == null) { return null }if (subject == '|||PR') { return { target = '' title = '' } }if (subject.startsWith('|||PR ')) { return { target = '' title = subject.slice(6).trim() } }if (subject.startsWith('|||PR|')) {let close = subject.indexOf(']')if (close < 7) { return null }let target = subject.slice(6, close)let rest = subject.slice(close + 1)if (rest != '' && !rest.startsWith(' ')) { return null }if (!safeName(target)) { return null }return { target = target title = rest.trim() }}return null}static isDigits = (s) => {if (s == '' || s.length > 9) { return false }let i = 0while (i < s.length) {let c = s.charCodeAt(i)if (c < 48 || c > 57) { return false }i = i + 1}return true}// the part of a version after its patch digits: only letters, digits, `.` and `-`static suffixOk = (s) => {let i = 0while (i < s.length) {let c = s.charCodeAt(i)if (!((c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || c == 45 || c == 46)) { return false }i = i + 1}return true}// `1.2.3` or `1.2.3a` → { major, minor, patch, text } or nullstatic parseVersion = (t) => {if (t == null || t.length > 32) { return null }let parts = t.split('.')if (parts.length < 3) { return null }if (!isDigits(parts[0]) || !isDigits(parts[1])) { return null }let rest = parts.slice(2).join('.')let n = 0while (n < rest.length && rest.charCodeAt(n) >= 48 && rest.charCodeAt(n) <= 57) { n = n + 1 }if (n == 0 || n > 9 || !suffixOk(rest.slice(n))) { return null }return { major = toNumber(parts[0]) minor = toNumber(parts[1]) patch = toNumber(rest.slice(0, n)) text = t }}// a commit subject → null (not a release) or { kind: 'patch' | 'med' | 'mj' | 'set', version, title }static parseRelease = (subject) => {if (subject == null) { return null }if (subject == '|||RL') { return { kind = 'patch' version = null title = '' } }if (subject.startsWith('|||RL ')) { return { kind = 'patch' version = null title = subject.slice(6).trim() } }if (subject.startsWith('|||RL|')) {let body = subject.slice(6)let sp = body.indexOf(' ')let token = sp < 0 ? body : body.slice(0, sp)let title = sp < 0 ? '' : body.slice(sp + 1).trim()if (token == 'med') { return { kind = 'med' version = null title = title } }if (token == 'mj') { return { kind = 'mj' version = null title = title } }let v = parseVersion(token)if (v == null) { return null }return { kind = 'set' version = v title = title }}return null}
Branches
- mainmain branch
Latest commits
- 090a20c6mission 002 (code order) 2/4: one lib/ file per topic — git.hl split into git (calls, branches, init, temp folder) / homepage / code / pulls / releases (+ git-helpers: paths, ids, |||PR/|||RL markers); repos-helpers, tickets-helpers, transport-helpers; util.hl = localtime + env, storage dir, addresses, lists, text checks, one newest-first sort (was 3 copies); the function routes out of project.hl into lib/api.hl (thin; plumbing in api-helpers.hl), sshgate.hl folded into api.hl + sshkeys.hl keyLine + repos.hl mayPush; 'Make main' and the merge answer out of the faces (code.hl makeMain, pulls.hl pullsView), one login helper (users.hl userOfLoginCode); project.hl is the map. Session-writing routes get &req + &server.sessions. gates 200/0, 46/0, 44/0; real-data identical except /login/failed now shows the parked reason for a browser that already had a session (the old copy-of-req lost it)mre
- 110c2799mission 002 (code order) 1/4: .hl files out of the root — lib/ (api, git, localtime, markdown, repos, sshgate, sshkeys, tickets, tokens, transport, users), components/styles.hl; jsoncheck.hl removed (imported nowhere); import paths only. gates 200/0, 46/0, 44/0; real-data reads + writes identicalmre
- fdfb4b1bgitoria: Hybriel master 06617221 (plugin allocators 3a781359 + 413f60e4, mpackdb 2cb7ae5e, http1 773de63e); gates 200/0, 46/0, 44/0mre
- 5b46ac84antcolony#40: LOG.md — missions 069/072 are antcolony missions (report paths on Byrodin)mre
- 5602ff41gitoria: Hybriel master 190aa11d (fc838894 GC correctness, #127 mountKids by reference, #126, #48) — tracker README flat; gates 200/0, 46/0, 44/0mre
- e85eaf01gitoria: 069 round 2 — hybriel 1a096ad3 not adopted (Markdown SSR still grows); browser gate waits for the server-side logout before restartmre
- 09ce4f3fgitoria: mission 069 re-vendor hybriel 8efba065 stopped (big SSR pages grow + slow down); lambda audit clean; old vendor keptmre
- 3dc43108antcolony#40: mission references point to the moved missionsmre
- 8d9450fdantcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
- 205d5fe4gitoria: Hybriel master ff51cf46; ssh keys/tokens no double rows (session sync); gates follow #20mre
- 9b27cb26gitoria#21: installable app (manifest, service worker, offline start page), own iconmre
- 68dcb603deploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
- e2deed6dgitoria#20: "Add code" only on the Code page of an empty repository, no collapsiblemre
- 8bb97ffddeploy.sh: never send .git or .gitignore to Byrodinmre
- fd981932State of 2026-09-27; bin/ no longer tracked (Hybriel commit is in README)mre
- 4a2d7125initial commitmre