Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] PoC for a Node.JS backend using nodegit #259

Draft
wants to merge 36 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6198242
Gitignore a few paths
julien-c Oct 8, 2020
83f7c72
(remove) simplest possible klaus.py server
julien-c Oct 8, 2020
b288c9f
[node] Lightweight scaffolding for an express app in Typescript
julien-c Oct 8, 2020
fb801c2
[node] PoC for tiny subset of features
julien-c Oct 8, 2020
2cac8fe
Name="klaus.py" for clarity
julien-c Oct 12, 2020
631de67
Handle nested repos
julien-c Oct 12, 2020
09237d8
cs(Add quotes around html attrs)
julien-c Oct 19, 2020
769bdd3
Update basic.py
julien-c Oct 19, 2020
cac1208
More complete PoC
julien-c Oct 20, 2020
70e96ed
blob view
julien-c Oct 20, 2020
3abb01f
Blame blob
julien-c Oct 20, 2020
12531a6
commit view
julien-c Oct 20, 2020
874ab4a
Better hljs integration + Fixup
julien-c Oct 20, 2020
8b376c4
Also support non-bare repos (very useful for debugging)
julien-c Oct 21, 2020
d271d9c
Link from commit to parent(s)
julien-c Oct 21, 2020
d1f8a85
Fixup h/t @pierrci
julien-c Oct 23, 2020
69323fa
upgrade deps
julien-c Oct 23, 2020
67ace25
Add readme
julien-c Oct 23, 2020
6eed736
Add helper button to sync all repos from origin
julien-c Oct 24, 2020
b327351
implement a "Check on GitHub" link that opens the "same" page on GitHub
julien-c Oct 24, 2020
94228dc
Support all DEFAULT_BRANCH natively
julien-c Oct 24, 2020
d39a77c
view_commit: display more info for dev purposes
julien-c Oct 24, 2020
f438804
Add missing tree/:rev route
julien-c Oct 24, 2020
c87919d
Tweaks
julien-c Oct 24, 2020
7702649
Tweak
julien-c Oct 24, 2020
a1f2e6f
even more tweaks
julien-c Oct 24, 2020
f3e85ad
cs
julien-c Oct 24, 2020
e3bbf49
commit history
julien-c Oct 24, 2020
a321038
Always keep the most generic routes at the end.
julien-c Oct 24, 2020
2688f86
Tweak to speed things up
julien-c Oct 24, 2020
b126751
mention tsc -w
julien-c Oct 26, 2020
26e700d
Example of how to setup source-map-support for TS
julien-c Oct 28, 2020
99b17e2
[/fetch_all] more robust error handling
julien-c Oct 28, 2020
9b5bbe4
Revert "Tweak to speed things up"
julien-c Oct 28, 2020
530007e
Improve perf of history(path)
julien-c Oct 28, 2020
ebcfcd4
Add perf note
julien-c Oct 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions node/app/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface BreadcrumbPath {
export class NotFoundError extends Error {}


export const repoNameFromRequest = (req: express.Request) => {
const repoNameFromRequest = (req: express.Request) => {
return req.params.namespace
? `${req.params.namespace}/${req.params.repo}`
: req.params.repo
Expand Down Expand Up @@ -57,9 +57,13 @@ export class Context {
}

async initialize(): Promise<void> {
try {
if (await Utils.fileExists(`${Repo.ROOT_REPOS}/${this.repoName}.git`)) {
/// bare repo
this.repo = await Git.Repository.openBare(`${Repo.ROOT_REPOS}/${this.repoName}.git`);
} catch {
} else if (await Utils.fileExists(`${Repo.ROOT_REPOS}/${this.repoName}/.git`)) {
/// non-bare repo
this.repo = await Git.Repository.open(`${Repo.ROOT_REPOS}/${this.repoName}/.git`);
} else {
throw new NotFoundError(`No such repository ${this.repoName}`);
}

Expand Down Expand Up @@ -157,6 +161,10 @@ export class BlobContext extends Context {
return this.blob.rawsize() > 10**9;
}

/**
* Highlight content with hljs,
* and store in this.data.
*/
renderText() {
const ext = Utils.trimPrefix(extname(this.path!), ".");
const str = this.blob.toString();
Expand Down
20 changes: 13 additions & 7 deletions node/app/Repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,23 @@ import { Utils } from '../lib/Utils';
export namespace Repo {
export const ROOT_REPOS = __rootDir+`/repositories`;

export function name(r: Git.Repository) {
return Utils.trimSuffix(path.relative(ROOT_REPOS, r.path()), '.git');
export function name(repo: Git.Repository) {
const rel = path.relative(ROOT_REPOS, repo.path());
if (rel.endsWith(`/.git`)) {
/// non-bare repo
return Utils.trimSuffix(rel, `/.git`);
} else {
/// bare repo
return Utils.trimSuffix(rel, '.git');
}
}

export async function refs(r: Git.Repository): Promise<{
export async function refs(repo: Git.Repository): Promise<{
tags: string[];
branches: string[];
}> {
const tags = await Git.Tag.list(r);
const branches = (await r.getReferences())
const tags = await Git.Tag.list(repo);
const branches = (await repo.getReferences())
.filter(x => x.isBranch())
.map(x => x.shorthand())
;
Expand All @@ -33,11 +40,10 @@ export namespace Repo {
): Promise<number> {
const revWalk = repo.createRevWalk();
revWalk.push(before.id());
let i = 1;
let i = 0;
/// ^^ Include `before` in the count.
while (true) {
try {
await revWalk.next();
julien-c marked this conversation as resolved.
Show resolved Hide resolved
i++;
} catch(err) {
if (err.errno === Git.Error.CODE.ITEROVER) {
Expand Down
12 changes: 12 additions & 0 deletions node/lib/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ export namespace Utils {
return arr.filter((x): x is T => x !== undefined);
}

/**
* Does local file exist.
*/
export async function fileExists(path: string): Promise<boolean> {
try {
await fs.promises.access(path);
return true;
} catch {
return false;
}
}

/**
* Recursive readdir matching fs.Dirent[]
*
Expand Down
6 changes: 4 additions & 2 deletions node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,21 @@ app.get(
* not containing a `/`.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see where you're coming from but at least in the software engineering world feature branches (feature/xyz) are very common.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes – for a v1 for the sake of simplicity I think this will work but we can always add support later

*/


/**
* Routes(html)
*/

app.get('/', async function(req, res) {
const repoFolders = await Utils.readdirREnt(
Repo.ROOT_REPOS,
(x) => x.name.endsWith(`.git`),
(x) => x.name === `.git` || x.name.endsWith(`.git`),
2
);
/// Assume top-level or nesting=1 folders in this dir
/// are our repos.
/// Also assume they are bare repos.
/// Update: Also support non-bare repos, but only at top-level.
const repos = await Promise.all(repoFolders.map(x => {
return Git.Repository.openBare(x);
}));
Expand Down Expand Up @@ -115,6 +116,7 @@ app.get('/:namespace/:repo/raw/:rev/*', rawBlob);
app.get( '/:repo/blame/:rev/*', blameBlob);
app.get('/:namespace/:repo/blame/:rev/*', blameBlob);


app.get( '/:repo/commit/:rev', viewCommit);
app.get('/:namespace/:repo/commit/:rev', viewCommit);

Expand Down
10 changes: 5 additions & 5 deletions node/views/repo_list.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
{{/eq}}
</span>
</h2>
<ul class=repolist>
<ul class="repolist">
{{#each items as |item|}}
<li>
<a
href="/{{repo_name item.repo}}"
href="/{{ repo_name item.repo }}"
>
<div class=name>{{repo_name item.repo}}</div>
<div class=last-updated>
last updated {{ call item.commit "date" }}
<div class="name">{{ repo_name item.repo }}</div>
<div class="last-updated">
last updated {{ dateUTC (call item.commit "date") }}
</div>
</a>
</li>
Expand Down