Skip to content

Commit 56f7995

Browse files
committed
refactor: refactor storage with intent types
1 parent 81b1f77 commit 56f7995

File tree

3 files changed

+81
-41
lines changed

3 files changed

+81
-41
lines changed

src/types/intent.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// TODO: 'completed' | 'cancelled'
2+
export type IntentStatus = 'created' | 'in_progress';
3+
4+
export type IntentionalCommit = {
5+
id: string;
6+
message: string;
7+
status: IntentStatus;
8+
metadata: {
9+
createdAt: string;
10+
startedAt?: string;
11+
// completedAt?: string;
12+
// cancelledAt?: string;
13+
branch?: string;
14+
};
15+
};
16+
17+
export type StorageData = {
18+
version: string;
19+
commits: IntentionalCommit[];
20+
};

src/utils/git.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import execa from 'execa';
12
import { simpleGit } from 'simple-git';
23

34
export const createGit = (cwd?: string) => simpleGit(cwd);
@@ -35,4 +36,39 @@ export async function getStatus(cwd?: string): Promise<string> {
3536
return JSON.stringify(status, null, 2);
3637
}
3738

39+
export async function hashObject(content: string, cwd?: string): Promise<string> {
40+
const { stdout } = await execa('git', ['hash-object', '-w', '--stdin'], { input: content, cwd });
41+
return stdout.trim();
42+
}
43+
44+
export async function createTree(treeContent: string, cwd?: string): Promise<string> {
45+
const { stdout } = await execa('git', ['mktree'], { input: treeContent, cwd });
46+
return stdout.trim();
47+
}
48+
49+
export async function createCommitTree(treeHash: string, message: string, cwd?: string): Promise<string> {
50+
const { stdout } = await execa('git', ['commit-tree', treeHash, '-m', message], { cwd });
51+
return stdout.trim();
52+
}
53+
54+
export async function updateRef(refName: string, commitHash: string, cwd?: string): Promise<void> {
55+
const git = createGit(cwd);
56+
await git.raw(['update-ref', refName, commitHash]);
57+
}
58+
59+
export async function deleteRef(refName: string, cwd?: string): Promise<void> {
60+
const git = createGit(cwd);
61+
await git.raw(['update-ref', '-d', refName]);
62+
}
63+
64+
export async function checkRefExists(refName: string, cwd?: string): Promise<boolean> {
65+
const git = createGit(cwd);
66+
try {
67+
await git.raw(['show-ref', '--verify', refName]);
68+
return true;
69+
} catch {
70+
return false;
71+
}
72+
}
73+
3874
export default createGit();

src/utils/storage.ts

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
11
import path from 'node:path';
2-
import execa from 'execa';
32
import fs from 'fs-extra';
3+
import type { IntentionalCommit, StorageData } from '../types/intent.js';
44
import { generateId } from './generateId.js';
55
import { getPackageInfo } from './get-package-info.js';
6-
import git, { checkIsRepo } from './git.js';
7-
8-
export type IntentionalCommit = {
9-
id: string;
10-
message: string;
11-
status: 'created' | 'in_progress';
12-
metadata: {
13-
createdAt: string;
14-
startedAt?: string;
15-
branch?: string;
16-
};
17-
};
18-
19-
export type StorageData = {
20-
version: string;
21-
commits: IntentionalCommit[];
22-
};
6+
import git, {
7+
checkIsRepo,
8+
hashObject,
9+
createTree,
10+
createCommitTree,
11+
updateRef,
12+
deleteRef,
13+
checkRefExists,
14+
} from './git.js';
2315

2416
export class GitIntentionalCommitStorage {
2517
private static instance: GitIntentionalCommitStorage;
@@ -77,7 +69,6 @@ export class GitIntentionalCommitStorage {
7769
}
7870
}
7971

80-
// NOTE: Migrate old data
8172
private migrateData(data: any): StorageData {
8273
return data;
8374
}
@@ -105,14 +96,12 @@ export class GitIntentionalCommitStorage {
10596
const commitsFile = await this.getCommitsFile();
10697
const content = JSON.stringify(data, null, 2);
10798

108-
const { stdout: hash } = await execa('git', ['hash-object', '-w', '--stdin'], { input: content, cwd: root });
109-
const treeContent = `100644 blob ${hash.trim()}\t${this.storageFilename}\n`;
110-
const { stdout: treeHash } = await execa('git', ['mktree'], { input: treeContent, cwd: root });
111-
const { stdout: commitHash } = await execa('git', ['commit-tree', treeHash.trim(), '-m', 'Update intent commits'], {
112-
cwd: root,
113-
});
99+
const hash = await hashObject(content, root);
100+
const treeContent = `100644 blob ${hash}\t${this.storageFilename}\n`;
101+
const treeHash = await createTree(treeContent, root);
102+
const commitHash = await createCommitTree(treeHash, 'Update intent commits', root);
114103

115-
await git.cwd(root).raw(['update-ref', `${this.REFS_PREFIX}/commits`, commitHash.trim()]);
104+
await updateRef(`${this.REFS_PREFIX}/commits`, commitHash, root);
116105
await fs.writeJSON(commitsFile, data, { spaces: 2 });
117106
}
118107

@@ -128,14 +117,14 @@ export class GitIntentionalCommitStorage {
128117
async addCommit(commit: Omit<IntentionalCommit, 'id'>): Promise<string> {
129118
const currentCommits = await this.loadCommits();
130119
const newCommitId = generateId(8);
120+
const newCommit = { ...commit, id: newCommitId };
131121

132122
const data: StorageData = {
133123
version: getPackageInfo().version,
134-
commits: [...currentCommits, { ...commit, id: newCommitId }],
124+
commits: [...currentCommits, newCommit],
135125
};
136126

137127
await this.saveCommitsData(data);
138-
139128
return newCommitId;
140129
}
141130

@@ -165,29 +154,24 @@ export class GitIntentionalCommitStorage {
165154
const root = await this.getGitRoot();
166155
const commitsFile = await this.getCommitsFile();
167156
await fs.remove(commitsFile);
168-
await git.cwd(root).raw(['update-ref', '-d', `${this.REFS_PREFIX}/commits`]);
157+
await deleteRef(`${this.REFS_PREFIX}/commits`, root);
169158
}
170159

171160
async initializeRefs(): Promise<void> {
172161
const root = await this.getGitRoot();
173162
await checkIsRepo(root);
174163

175-
try {
176-
await git.cwd(root).raw(['show-ref', '--verify', `${this.REFS_PREFIX}/commits`]);
177-
} catch {
164+
const refExists = await checkRefExists(`${this.REFS_PREFIX}/commits`, root);
165+
if (!refExists) {
178166
const initialData = this.getInitialData();
179167
const content = JSON.stringify(initialData, null, 2);
180168

181-
const { stdout: hash } = await execa('git', ['hash-object', '-w', '--stdin'], { input: content, cwd: root });
182-
const treeContent = `100644 blob ${hash.trim()}\t${this.storageFilename}\n`;
183-
const { stdout: treeHash } = await execa('git', ['mktree'], { input: treeContent, cwd: root });
184-
const { stdout: commitHash } = await execa(
185-
'git',
186-
['commit-tree', treeHash.trim(), '-m', 'Initialize intent commits'],
187-
{ cwd: root }
188-
);
169+
const hash = await hashObject(content, root);
170+
const treeContent = `100644 blob ${hash}\t${this.storageFilename}\n`;
171+
const treeHash = await createTree(treeContent, root);
172+
const commitHash = await createCommitTree(treeHash, 'Initialize intent commits', root);
189173

190-
await git.cwd(root).raw(['update-ref', `${this.REFS_PREFIX}/commits`, commitHash.trim()]);
174+
await updateRef(`${this.REFS_PREFIX}/commits`, commitHash, root);
191175
}
192176
}
193177
}

0 commit comments

Comments
 (0)