Skip to content

Commit 19aea29

Browse files
committed
feat(chrono): add head entry repository
1 parent ade24f4 commit 19aea29

File tree

9 files changed

+125
-31
lines changed

9 files changed

+125
-31
lines changed

packages/chrono/src/ChronoApp.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,40 @@ import IHash from './gateways/IHash'
33

44
import IBlobRepository from './repositories/IBlobRepository'
55
import IObjectRepository from './repositories/IObjectRepository'
6+
import IIndexEntryRepository from './repositories/IIndexEntryRepository'
7+
import IHeadEntryRepository from './repositories/IHeadEntryRepository'
68

79
import LocalObjectRepository from './repositories/implementations/LocalObjectRepository'
810
import LocalBlobRepository from './repositories/implementations/LocalBlobRepository'
11+
import LocalIndexEntryRepository from './repositories/implementations/LocalIndexEntryRepository'
12+
import LocalHeadEntryRepository from './repositories/implementations/LocalHeadEntryRepository'
913

1014
import InitUseCase from './use-cases/InitUseCase'
1115
import CatFileUseCase from './use-cases/CatFileUseCase'
1216
import HashFileUseCase from './use-cases/HashEntryUseCase'
1317
import RemoveUseCase from './use-cases/RemoveUseCase'
1418
import CommitUseCase from './use-cases/CommitUseCase'
1519
import StatusUseCase from './use-cases/StatusUseCase'
16-
import IIndexEntryRepository from './repositories/IIndexEntryRepository'
17-
import LocalEntryRepository from './repositories/implementations/LocalEntryRepository'
1820
import AddUseCase from './use-cases/AddUseCase'
1921
import ListFilesUseCase from './use-cases/ListFilesUseCase'
2022

2123
export default class ChronoApp {
24+
private readonly drive: IDrive
25+
private readonly hash: IHash
26+
2227
private readonly objectRepository: IObjectRepository
2328
private readonly blobRepository: IBlobRepository
24-
private readonly entryRepository: IIndexEntryRepository
29+
private readonly indexEntryRepository: IIndexEntryRepository
30+
private readonly headEntryRepository: IHeadEntryRepository
31+
32+
constructor(drive: IDrive, hash: IHash) {
33+
this.drive = drive
34+
this.hash = hash
2535

26-
constructor(
27-
private readonly drive: IDrive,
28-
private readonly hash: IHash
29-
) {
3036
this.objectRepository = new LocalObjectRepository(drive, hash)
3137
this.blobRepository = new LocalBlobRepository(drive, hash)
32-
this.entryRepository = new LocalEntryRepository(drive)
38+
this.indexEntryRepository = new LocalIndexEntryRepository(drive)
39+
this.headEntryRepository = new LocalHeadEntryRepository(drive, this.objectRepository)
3340
}
3441

3542
public async init() {
@@ -50,35 +57,35 @@ export default class ChronoApp {
5057
return useCase.execute({ objectHash })
5158
}
5259

53-
public async addEntry(path: string) {
60+
public async addEntry(...path: string[]) {
5461
const useCase = new AddUseCase(
5562
this.drive,
5663
this.objectRepository,
5764
this.blobRepository,
58-
this.entryRepository
65+
this.indexEntryRepository
5966
)
6067

6168
return useCase.execute({ path })
6269
}
6370

6471
public async removeEntry(path: string) {
65-
const useCase = new RemoveUseCase(this.drive, this.entryRepository)
72+
const useCase = new RemoveUseCase(this.drive, this.indexEntryRepository)
6673

6774
return useCase.execute({ path })
6875
}
6976

70-
public async list() {
71-
const useCase = new ListFilesUseCase(this.entryRepository)
77+
public async list(stage = false) {
78+
const useCase = new ListFilesUseCase(this.indexEntryRepository, this.headEntryRepository)
7279

73-
return useCase.execute()
80+
return useCase.execute({ stage })
7481
}
7582

7683
public async commit(message: string, body?: string) {
7784
const useCase = new CommitUseCase(
7885
this.drive,
7986
this.objectRepository,
8087
this.blobRepository,
81-
this.entryRepository
88+
this.indexEntryRepository
8289
)
8390

8491
return useCase.execute({ message, body })
@@ -89,7 +96,7 @@ export default class ChronoApp {
8996
this.drive,
9097
this.objectRepository,
9198
this.blobRepository,
92-
this.entryRepository
99+
this.indexEntryRepository
93100
)
94101

95102
return useCase.execute()

packages/chrono/src/entities/ChronoObjectTree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import ChronoObject from './ChronoObject'
33
export interface ChronoObjectTreeEntry {
44
path: string
55
hash: string
6-
type: string
6+
type: 'blob' | 'tree'
77
}
88

99
export default class ChronoObjectTree extends ChronoObject {
@@ -17,7 +17,7 @@ export default class ChronoObjectTree extends ChronoObject {
1717
type,
1818
hash,
1919
path,
20-
}
20+
} as ChronoObjectTreeEntry
2121
})
2222
}
2323

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default class HeadEntry {
2+
public path: string
3+
public hash: string
4+
public type: 'blob' | 'tree' = 'blob'
5+
6+
public static from(payload: Pick<HeadEntry, 'path' | 'hash' | 'type'>) {
7+
const head = new HeadEntry()
8+
9+
Object.assign(head, payload)
10+
11+
return head
12+
}
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import HeadEntry from '../entities/HeadEntry'
2+
3+
export default interface IHeadEntryRepository {
4+
findAll(): Promise<HeadEntry[]>
5+
}

packages/chrono/src/repositories/IStageItemRepository.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import ChronoObjectTree from '../../entities/ChronoObjectTree'
2+
import HeadEntry from '../../entities/HeadEntry'
3+
import IDrive from '../../gateways/IDrive'
4+
import HelperService from '../../services/HelperService'
5+
import IHeadEntryRepository from '../IHeadEntryRepository'
6+
import IObjectRepository from '../IObjectRepository'
7+
8+
export default class LocalHeadEntryRepository implements IHeadEntryRepository {
9+
constructor(
10+
private readonly drive: IDrive,
11+
private readonly objectRepository: IObjectRepository
12+
) {}
13+
14+
public async findEntriesFromTree(treeHash: string, basePath = '') {
15+
const entries = [] as HeadEntry[]
16+
17+
const object = await this.objectRepository.findOrFail(treeHash)
18+
19+
const tree = new ChronoObjectTree(object.content)
20+
21+
for await (const e of tree.entries) {
22+
const headEntry = HeadEntry.from({
23+
path: `${basePath}${e.path}`,
24+
hash: e.hash,
25+
type: e.type,
26+
})
27+
28+
entries.push(headEntry)
29+
30+
if (e.type === 'tree') {
31+
const childEntries = await this.findEntriesFromTree(e.hash, `${headEntry.path}/`)
32+
33+
entries.push(...childEntries)
34+
}
35+
}
36+
37+
return entries
38+
}
39+
40+
public findAll: IHeadEntryRepository['findAll'] = async () => {
41+
const contents = await this.drive.read('.chrono/head')
42+
43+
const hash = HelperService.decode(contents)
44+
45+
if (!hash) {
46+
return []
47+
}
48+
49+
const object = await this.objectRepository.findOrFail(hash)
50+
51+
if (object.type === 'commit') {
52+
return this.findEntriesFromTree(object.head.tree)
53+
}
54+
55+
return []
56+
}
57+
}

packages/chrono/src/repositories/implementations/LocalEntryRepository.ts renamed to packages/chrono/src/repositories/implementations/LocalIndexEntryRepository.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import IDrive from '../../gateways/IDrive'
33
import HelperService from '../../services/HelperService'
44
import IIndexEntryRepository from '../IIndexEntryRepository'
55

6-
export default class LocalEntryRepository implements IIndexEntryRepository {
6+
export default class LocalIndexEntryRepository implements IIndexEntryRepository {
77
constructor(private readonly drive: IDrive) {}
88

99
public findAll: IIndexEntryRepository['findAll'] = async () => {
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
export default class HelperService {
2+
public static basename(path: string) {
3+
const parts = path.split('/')
4+
5+
return parts[parts.length - 1]
6+
}
7+
28
public static encode(content: string) {
39
return new TextEncoder().encode(content)
410
}
511

6-
public static decode(content: Uint8Array) {
12+
public static decode(content?: Uint8Array | null) {
13+
if (!content) {
14+
return ''
15+
}
716
return new TextDecoder('utf-8').decode(content)
817
}
918
}
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1+
import IHeadEntryRepository from '../repositories/IHeadEntryRepository'
12
import IIndexEntryRepository from '../repositories/IIndexEntryRepository'
23

4+
interface Params {
5+
stage: boolean
6+
}
37
export default class ListFilesUseCase {
4-
constructor(private readonly entryRepository: IIndexEntryRepository) {}
8+
constructor(
9+
private readonly indexEntryRepository: IIndexEntryRepository,
10+
private readonly headEntryRepository: IHeadEntryRepository
11+
) {}
12+
13+
async execute({ stage }: Params) {
14+
if (stage) {
15+
return this.indexEntryRepository.findAll()
16+
}
517

6-
async execute() {
7-
return this.entryRepository.findAll()
18+
return this.headEntryRepository.findAll()
819
}
920
}

0 commit comments

Comments
 (0)