Skip to content

Commit

Permalink
refactor: move formatgit2json to core lib (#130)
Browse files Browse the repository at this point in the history
refactor: move formatgit2json to core lib

chore: draft cli for rendering graph history
  • Loading branch information
nadilas authored Feb 16, 2024
2 parents 8d4a177 + 338ac45 commit ac61844
Show file tree
Hide file tree
Showing 43 changed files with 20,270 additions and 11,860 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,3 @@
#### Authors: 1

- [@nadilas](https://github.com/nadilas)

40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ogre

An in-memory git-like repository for objects for when you need to
An in-memory git-like repository for objects for when you need to
keep the history around for a bit longer.

[![codecov](https://codecov.io/gh/dotindustries/ogre/branch/main/graph/badge.svg?token=23M014CWLK)](https://codecov.io/gh/dotindustries/ogre) [![Test coverage](https://github.com/dotindustries/ogre/actions/workflows/coverage.yml/badge.svg)](https://github.com/dotindustries/ogre/actions/workflows/coverage.yml)
Expand All @@ -13,43 +13,43 @@ keep the history around for a bit longer.
- Checkout
- Visualization via `@dotinc/ogre-react`
- Merge
- fast-forward
- fast-forward

## Usage

```typescript
const repo = new Repository(new ComplexObject())
const repo = new Repository(new ComplexObject());

// apply changes
repo.data.name = 'my name'
repo.data.description = 'now we have a description'
repo.data.name = "my name";
repo.data.description = "now we have a description";

// commit changes
const init = await repo.commit('initial commit', 'author <[email protected]>')
// commit changes
const init = await repo.commit("initial commit", "author <[email protected]>");
// create a branch named savepoint pointing to the last commit
repo.createBranch('savepoint')
repo.createBranch("savepoint");

// switch to new branch
repo.checkout('add_details', true)
repo.checkout("add_details", true);

// apply changes
repo.data.name = 'a fancier name'
repo.data.name = "a fancier name";

// a) commit & merge
await repo.commit('change name', 'author <[email protected]>')
repo.checkout('main')
repo.merge('add_details')
repo.tag('v1.0.0')
await repo.commit("change name", "author <[email protected]>");
repo.checkout("main");
repo.merge("add_details");
repo.tag("v1.0.0");

// or b) discard change and go back
// by using the branch name
repo.checkout('main')
// by using the commit hash in a detached state
repo.checkout(init)
// by using the branch name
repo.checkout("main");
// by using the commit hash in a detached state
repo.checkout(init);
```

## TODO

- [ ] Merge
- [ ] recursive
- [ ] octopus
- [ ] recursive
- [ ] octopus
12 changes: 12 additions & 0 deletions apps/ogre-cli/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.yml]
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions apps/ogre-cli/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
2 changes: 2 additions & 0 deletions apps/ogre-cli/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
1 change: 1 addition & 0 deletions apps/ogre-cli/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
60 changes: 60 additions & 0 deletions apps/ogre-cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "@dotinc/ogre-cli",
"version": "0.0.0",
"license": "MIT",
"bin": "dist/cli.js",
"type": "module",
"engines": {
"node": ">=16"
},
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"test": "prettier --check . && xo && ava"
},
"files": [
"dist"
],
"dependencies": {
"meow": "^11.0.0",
"@gitgraph/core": "1.5.0",
"chalk": "^5.3.0",
"color-convert": "^2.0.1",
"lodash": "^4.17.21"
},
"devDependencies": {
"@sindresorhus/tsconfig": "^3.0.1",
"@types/react": "^18.0.32",
"@vdemedes/prettier-config": "^2.0.1",
"ava": "^5.2.0",
"chalk": "^5.2.0",
"eslint-config-xo-react": "^0.27.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.8.7",
"ts-node": "^10.9.1",
"typescript": "^5.0.3",
"xo": "^0.53.1",
"@types/lodash": "^4.14.202",
"@types/node": "^20.11.17",
"auto-changelog": "^2.4.0",
"@types/color-convert": "^2.0.3"
},
"ava": {
"extensions": {
"ts": "module",
"tsx": "module"
},
"nodeArguments": [
"--loader=ts-node/esm"
]
},
"xo": {
"extends": "xo-react",
"prettier": true,
"rules": {
"react/prop-types": "off"
}
},
"prettier": "@vdemedes/prettier-config"
}
25 changes: 25 additions & 0 deletions apps/ogre-cli/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ogre-cli

> This readme is automatically generated by [create-ink-app](https://github.com/vadimdemedes/create-ink-app)
## Install

```bash
$ npm install --global ogre-cli
```

## CLI

```
$ ogre-cli --help
Usage
$ ogre-cli
Options
--name Your name
Examples
$ ogre-cli --name=Jane
Hello, Jane
```
70 changes: 70 additions & 0 deletions apps/ogre-cli/source/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env node
import meow from 'meow';

import {formatGit2Json, Repository} from '@dotinc/ogre';
import {GitgraphUserApi} from '@gitgraph/core';

import {Gitgraph, render} from './graph/index.js';

const cli = meow(
`
Usage
$ ogre-cli
Options
--name Your name
Examples
$ ogre-cli --name=Jane
Hello, Jane
`,
{
importMeta: import.meta,
flags: {
name: {
type: 'string',
},
},
},
);

interface someClass {
name: string;
description: string;
}

const run = async ({name = 'author'}: {name?: string}) => {
const graph = new Gitgraph();

let author = `${name} <${name}@email.info>`;
const r = new Repository<someClass>({description: '', name}, {});
r.data.name = 'new name';
r.data.description = 'first description';
await r.commit('initial commit', author);

r.checkout('desc-up', true);
r.data.description = 'some longer different description';
await r.commit('change desc', author);

r.data.description = 'correct mistake made in prev description';
await r.commit('fix desc', author);

r.createBranch('another_branch');

r.data.description = 'yet another correction';
await r.commit('typo fix', author);

r.checkout('main');
r.merge('desc-up');

const history = r.getHistory();

// workaround to give an empty update method, otherwise we have window not defined issues
const graphuserapi = new GitgraphUserApi(graph, () => {});
graphuserapi.import(formatGit2Json(history));

render(graph);
console.log('finished rendering');
};

run({name: cli.flags.name});
123 changes: 123 additions & 0 deletions apps/ogre-cli/source/graph/buffer-graph-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import * as readline from 'readline';

import {GraphMap, ILogGraph} from './compute-graph-map/index.js';
import consoleGraphLogger from './console-graph-logger.js';

const DEFAULT_BUFFER_LENGTH = 10;

const bufferGraphLogger: ILogGraph = graph => {
let start = 0;

readline.emitKeypressEvents(process.stdin);

// Capture keypress events without having to hit "Enter".
if (process.stdin.setRawMode) {
process.stdin.setRawMode(true);
}

process.stdin.on('keypress', (_str, key: readline.Key) => {
// Implement `less`-style commands.
// https://en.wikipedia.org/wiki/Less_(Unix)#Frequently_used_commands
if (key.name === 'q') process.exit();
if (key.ctrl && key.name === 'c') process.exit();

if (key.name === 'up') moveOneLineUp();
if (key.name === 'k') moveOneLineUp();
if (key.name === 'b') moveOnePageUp();
if (key.name === 'g') moveToTop();
if (key.sequence === '<') moveToTop();

if (key.name === 'down') moveOneLineDown();
if (key.name === 'j') moveOneLineDown();
if (key.name === 'return') moveOneLineDown();
if (key.name === 'space') moveOnePageDown();
if (key.shift && key.name === 'g') moveToBottom();
if (key.sequence === '>') moveToBottom();
});

process.stdout.on('resize', () => {
const displayedBufferLength = graph.length - start;
if (bufferLength() >= displayedBufferLength) {
start = Math.max(top(), bottom());
}

render();
});

render();

function top() {
return 0;
}

function bottom() {
return graph.length - bufferLength();
}

function moveOneLineUp() {
moveUpOf(1);
}

function moveOnePageUp() {
moveUpOf(bufferLength());
}

function moveToTop() {
moveUpOf(start);
}

function moveUpOf(lines: number) {
if (start === 0) return;
start = Math.max(start - lines, top());
render();
}

function moveOneLineDown() {
moveDownOf(1);
}

function moveOnePageDown() {
moveDownOf(bufferLength());
}

function moveToBottom() {
moveDownOf(graph.length);
}

function moveDownOf(lines: number) {
if (end() >= graph.length) return;
start = Math.min(start + lines, bottom());
render();
}

function render() {
clear();
consoleGraphLogger(getBuffer());
}

function clear() {
// ANSI Escape Sequence for `<ESC>c` which is the escape code
// for resetting the terminal (clears the screen and buffer).
// https://en.wikipedia.org/wiki/ANSI_escape_code
process.stdout.write('\x1b[2J');
}

function getBuffer(): GraphMap {
return graph.slice(start, end());
}

function end() {
return start + bufferLength();
}
};

export function bufferLength(): number {
const length = process.env['BUFFER_LENGTH']
? parseInt(process.env['BUFFER_LENGTH'], 10)
: process.stdout.rows || DEFAULT_BUFFER_LENGTH;

// Length should be 0-indexed to compare with arrays.
return length - 1;
}

export default bufferGraphLogger;
Loading

0 comments on commit ac61844

Please sign in to comment.