gitoria
All repositories: gitoria
5.5 KB
// components/codebrowser.hl — THE CODE BROWSER (ticket #9, gitoria#16), composed into the three code pages:// code.hl (/code, /code/<path>: the main branch), branch.hl (/branch/<name>[/<path>]), commit.hl// (/commit/<id>[/<path>]); `kind` ('code' | 'branch' | 'commit') and `rest` (the part after /<kind>/) come from the// page. Rendered on the SERVER with its content: the repo from the request's host, the tree / file / branches /// commits from git (git.hl browseNow — hl:proc run() waits, hybriel#80) — in the first HTML and in every hl:web navigation.import { repoAt, repoBySlug, setMainBranch, ownsRepo } from '../repos.hl'import { browseNow, branchNames } from '../git.hl'import { withRefParts } from '../tickets.hl'import { slugOfHost, userOfSession } from '../users.hl'host = nullsession = nullkind = 'code'rest = ''slug = slugOfHost(host)repo = repoAt(slug)hasRepo = repo != nullcodeData = repo != null ? withRefParts(browseNow(slug, kind, rest, repo.branch, ownsRepo(slug, session)), repo.ticketsProject) : nullcodeShown = codeData != null && !codeData.isMessagecodeMessage = codeData != null && codeData.isMessagecodeText = codeData != null && codeData.isMessage ? codeData.message : ''codeError = ''View {codeView {if (hasRepo) {if (codeMessage) { p { id = "codemessage" class = "empty" codeText } }if (codeShown) {codeBrowser {codeHead {span { id = "codekind" class = "muted" codeData.kindLabel }strong { id = "coderef" codeData.refLabel }latestCommit {a { id = "commitlink" href = codeData.commitHref codeData.short }span { id = "commitsubject" for (pt of codeData.subjectParts) { if (pt.isText) { span { pt.text } } if (pt.isLink) { a { class = "ticketref" href = pt.href pt.text } } } }span { class = "muted" codeData.author }time { codeData.date }}}pathCrumbs { id = "crumbs"for (c of codeData.crumbs) {if (c.linked) { a { href = c.href c.name } span { class = "muted" "/" } }if (c.last) { strong { c.name } }}}if (codeData.isTree) {if (codeData.noEntries) { p { id = "noentries" class = "empty" "This folder is empty." } }ul { id = "entries"for (e of codeData.entries) {li {if (e.isDir) { a { class = "dir" href = e.href e.name } }if (e.isFile) { a { class = "file" href = e.href e.name } }if (e.isOther) { span { class = "file" e.name } }span { class = "muted" e.size }}}}}if (codeData.isFile) {codeFile { id = "codefile"p { class = "muted" codeData.fileSize }if (codeData.binary) { p { id = "binary" class = "empty" "This file is not text (or not UTF-8) — not shown." } }if (codeData.tooBig) { p { id = "toobig" class = "empty" "This file is too large to show here." } }ol { id = "lines"for (ln of codeData.lines) { li { code { ln.text } } }}if (codeData.truncated) { p { id = "linestruncated" class = "muted" "Only the first lines are shown." } }}}codeSide {section { id = "branches"h2 { "Branches" }ul {for (b of codeData.branches) {li {if (b.isCurrent) { strong { b.name } }if (b.notCurrent) { a { href = b.href b.name } }if (b.isDefault) { span { class = "muted" "main branch" } }if (b.canSet) { button { class = "quiet setmain" type = "button" value = b.name "Make main" on click(e) { emit setMain(e.target.value) } } }}}}p { id = "codeerror" class = "message" codeError }}section { id = "commits"h2 { "Latest commits" }ul {for (c of codeData.commits) {li {a { href = c.href c.short }span { for (pt of c.parts) { if (pt.isText) { span { pt.text } } if (pt.isLink) { a { class = "ticketref" href = pt.href pt.text } } } }span { class = "muted" c.author }time { c.date }}}}}}}}}}}// "Make main" (the owner): the face answers with the same view, read again with the new main branchon setMain(name) {codeError = ''let r = emit server gitoriaSetBranch(slug, name, kind, rest)if (r == null || r.error != null) {codeError = r != null ? r.error : 'could not change the main branch'return null}codeData = r.resultcodeShown = !r.result.isMessagecodeMessage = r.result.isMessagecodeText = r.result.isMessage ? r.result.message : ''}on server gitoriaSetBranch(slugOf, name, kindOf, restOf, session) {if (session == null || repoAt(slugOf) == null) { return { error = 'could not change the main branch' } }if (kindOf != 'code' && kindOf != 'branch' && kindOf != 'commit') { return { error = 'could not change the main branch' } }if (restOf == null || hlTypeName(restOf) != 'String' || restOf.length > 500 || name == null || hlTypeName(name) != 'String') { return { error = 'could not change the main branch' } }let u = userOfSession(session)if (u == null || !ownsRepo(slugOf, session)) { return { error = 'only the owner can change the main branch' } }let known = []branchNames(slugOf, (names) => {known = namesreturn null})if (!known.includes(name)) { return { error = 'no such branch' } }let r = setMainBranch(u.id, slugOf, name)if (r.error != null) { return { error = r.error } }return { result = withRefParts(browseNow(slugOf, kindOf, restOf, name, true), repoAt(slugOf).ticketsProject) }}
Branches
- mainmain branch