gites: colorful git tree viewer
Tauri 2 + Vue app that draws the commit graph of the repository given on the command line. Branches can be hidden one by one or by patterns, runs of plain commits fold into a dotted line, and everything is reachable from the keyboard.
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import type { Ref } from "./types";
|
||||
|
||||
export interface TreeNode {
|
||||
/** One `/`-separated part of the name. */
|
||||
label: string;
|
||||
/** The name up to and including this part; unique within one tree. */
|
||||
path: string;
|
||||
children: TreeNode[];
|
||||
/** Set when a ref ends here. A node can be both a ref and a folder (`a` and `a/b`). */
|
||||
ref?: Ref;
|
||||
}
|
||||
|
||||
/** Splits short names by `/` into a tree. Folders come before refs, each sorted by name. */
|
||||
export function buildTree(items: { short: string; ref: Ref }[]): TreeNode[] {
|
||||
const root: TreeNode = { label: "", path: "", children: [] };
|
||||
for (const { short, ref } of items) {
|
||||
let node = root;
|
||||
for (const part of short.split("/")) {
|
||||
const path = node.path ? `${node.path}/${part}` : part;
|
||||
let child = node.children.find((c) => c.label === part);
|
||||
if (!child) {
|
||||
child = { label: part, path, children: [] };
|
||||
node.children.push(child);
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
node.ref = ref;
|
||||
}
|
||||
const sort = (nodes: TreeNode[]) => {
|
||||
nodes.sort(
|
||||
(a, b) => Number(b.children.length > 0) - Number(a.children.length > 0) || a.label.localeCompare(b.label),
|
||||
);
|
||||
nodes.forEach((n) => sort(n.children));
|
||||
};
|
||||
sort(root.children);
|
||||
return root.children;
|
||||
}
|
||||
|
||||
/** Every ref in the subtree. */
|
||||
export function refsUnder(node: TreeNode): Ref[] {
|
||||
return [...(node.ref ? [node.ref] : []), ...node.children.flatMap(refsUnder)];
|
||||
}
|
||||
Reference in New Issue
Block a user