refactor(core): consolidate filesystem services (#30447)

This commit is contained in:
Dax 2026-06-02 16:09:26 -04:00 committed by GitHub
commit 604a5f781f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
153 changed files with 2542 additions and 4301 deletions

View file

@ -1,6 +1,6 @@
import path from "path"
import { Context, Effect, Layer, Schema } from "effect"
import { AppFileSystem } from "./filesystem"
import { FSUtil } from "./fs-util"
import { Git } from "./git"
import { Global } from "./global"
import { Repository } from "./repository"
@ -119,139 +119,142 @@ export const validateBranch = Effect.fn("RepositoryCache.validateBranch")(functi
})
})
export const layer: Layer.Layer<
Service,
never,
AppFileSystem.Service | Git.Service | EffectFlock.Service | Global.Service
> = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* AppFileSystem.Service
const git = yield* Git.Service
const flock = yield* EffectFlock.Service
const global = yield* Global.Service
export const layer: Layer.Layer<Service, never, FSUtil.Service | Git.Service | EffectFlock.Service | Global.Service> =
Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
const git = yield* Git.Service
const flock = yield* EffectFlock.Service
const global = yield* Global.Service
return Service.of({
ensure: Effect.fn("RepositoryCache.ensure")(function* (input) {
if (input.branch) yield* validateBranch(input.branch)
return Service.of({
ensure: Effect.fn("RepositoryCache.ensure")(function* (input) {
if (input.branch) yield* validateBranch(input.branch)
const repository = input.reference.label
const localPath = Repository.cachePath(global.repos, input.reference)
const cloneTarget = Repository.parse(input.reference.remote) ?? input.reference
const repository = input.reference.label
const localPath = Repository.cachePath(global.repos, input.reference)
const cloneTarget = Repository.parse(input.reference.remote) ?? input.reference
return yield* flock
.withLock(
Effect.gen(function* () {
yield* cacheOperation(fs.ensureDir(path.dirname(localPath)), "ensure cache directory", localPath)
return yield* flock
.withLock(
Effect.gen(function* () {
yield* cacheOperation(fs.ensureDir(path.dirname(localPath)), "ensure cache directory", localPath)
const exists = yield* fs.existsSafe(localPath)
const hasGitDir = yield* fs.existsSafe(path.join(localPath, ".git"))
const origin = hasGitDir ? yield* git.origin(localPath) : undefined
const originReference = origin ? Repository.parse(origin) : undefined
const reuse = hasGitDir && Boolean(originReference && Repository.same(originReference, cloneTarget))
if (exists && !reuse) {
yield* cacheOperation(fs.remove(localPath, { recursive: true }), "remove stale cache", localPath)
}
const currentBranch = reuse ? yield* git.branch(localPath) : undefined
const status = statusForRepository({
reuse,
refresh: input.refresh,
branchMatches: input.branch ? currentBranch === input.branch : undefined,
})
if (status === "cloned") {
const result = yield* git
.clone({ remote: input.reference.remote, target: localPath, branch: input.branch })
.pipe(Effect.mapError((error) => new CloneFailedError({ repository, message: errorMessage(error) })))
if (result.exitCode !== 0) {
return yield* new CloneFailedError({
repository,
message: resultMessage(result, `Failed to clone ${repository}`),
})
}
}
if (status === "refreshed") {
const fetch = yield* git
.fetch(localPath)
.pipe(Effect.mapError((error) => new FetchFailedError({ repository, message: errorMessage(error) })))
if (fetch.exitCode !== 0) {
return yield* new FetchFailedError({
repository,
message: resultMessage(fetch, `Failed to refresh ${repository}`),
})
const exists = yield* fs.existsSafe(localPath)
const hasGitDir = yield* fs.existsSafe(path.join(localPath, ".git"))
const origin = hasGitDir ? yield* git.origin(localPath) : undefined
const originReference = origin ? Repository.parse(origin) : undefined
const reuse = hasGitDir && Boolean(originReference && Repository.same(originReference, cloneTarget))
if (exists && !reuse) {
yield* cacheOperation(fs.remove(localPath, { recursive: true }), "remove stale cache", localPath)
}
if (input.branch) {
const requestedBranch = input.branch
const fetchBranch = yield* git
.fetchBranch(localPath, requestedBranch)
const currentBranch = reuse ? yield* git.branch(localPath) : undefined
const status = statusForRepository({
reuse,
refresh: input.refresh,
branchMatches: input.branch ? currentBranch === input.branch : undefined,
})
if (status === "cloned") {
const result = yield* git
.clone({ remote: input.reference.remote, target: localPath, branch: input.branch })
.pipe(
Effect.mapError((error) => new CloneFailedError({ repository, message: errorMessage(error) })),
)
if (result.exitCode !== 0) {
return yield* new CloneFailedError({
repository,
message: resultMessage(result, `Failed to clone ${repository}`),
})
}
}
if (status === "refreshed") {
const fetch = yield* git
.fetch(localPath)
.pipe(
Effect.mapError((error) => new FetchFailedError({ repository, message: errorMessage(error) })),
)
if (fetchBranch.exitCode !== 0) {
if (fetch.exitCode !== 0) {
return yield* new FetchFailedError({
repository,
message: resultMessage(fetchBranch, `Failed to fetch ${requestedBranch}`),
message: resultMessage(fetch, `Failed to refresh ${repository}`),
})
}
const checkout = yield* git.checkout(localPath, requestedBranch).pipe(
Effect.mapError(
(error) =>
new CheckoutFailedError({
repository,
branch: requestedBranch,
message: errorMessage(error),
}),
),
)
if (checkout.exitCode !== 0) {
return yield* new CheckoutFailedError({
if (input.branch) {
const requestedBranch = input.branch
const fetchBranch = yield* git
.fetchBranch(localPath, requestedBranch)
.pipe(
Effect.mapError((error) => new FetchFailedError({ repository, message: errorMessage(error) })),
)
if (fetchBranch.exitCode !== 0) {
return yield* new FetchFailedError({
repository,
message: resultMessage(fetchBranch, `Failed to fetch ${requestedBranch}`),
})
}
const checkout = yield* git.checkout(localPath, requestedBranch).pipe(
Effect.mapError(
(error) =>
new CheckoutFailedError({
repository,
branch: requestedBranch,
message: errorMessage(error),
}),
),
)
if (checkout.exitCode !== 0) {
return yield* new CheckoutFailedError({
repository,
branch: requestedBranch,
message: resultMessage(checkout, `Failed to checkout ${requestedBranch}`),
})
}
}
const reset = yield* git
.reset(localPath, yield* resetTarget(git, localPath, input.branch))
.pipe(
Effect.mapError((error) => new ResetFailedError({ repository, message: errorMessage(error) })),
)
if (reset.exitCode !== 0) {
return yield* new ResetFailedError({
repository,
branch: requestedBranch,
message: resultMessage(checkout, `Failed to checkout ${requestedBranch}`),
message: resultMessage(reset, `Failed to reset ${repository}`),
})
}
}
const reset = yield* git
.reset(localPath, yield* resetTarget(git, localPath, input.branch))
.pipe(Effect.mapError((error) => new ResetFailedError({ repository, message: errorMessage(error) })))
if (reset.exitCode !== 0) {
return yield* new ResetFailedError({
repository,
message: resultMessage(reset, `Failed to reset ${repository}`),
})
}
}
return {
repository,
host: input.reference.host,
remote: input.reference.remote,
localPath,
status,
head: yield* git.head(localPath),
branch: yield* git.branch(localPath),
} satisfies Result
}),
`repository-cache:${localPath}`,
)
.pipe(
Effect.mapError((error) =>
isError(error) ? error : new LockFailedError({ localPath, message: errorMessage(error) }),
),
)
}),
})
}),
)
return {
repository,
host: input.reference.host,
remote: input.reference.remote,
localPath,
status,
head: yield* git.head(localPath),
branch: yield* git.branch(localPath),
} satisfies Result
}),
`repository-cache:${localPath}`,
)
.pipe(
Effect.mapError((error) =>
isError(error) ? error : new LockFailedError({ localPath, message: errorMessage(error) }),
),
)
}),
})
}),
)
export const defaultLayer: Layer.Layer<Service> = layer.pipe(
Layer.provide(EffectFlock.defaultLayer),
Layer.provide(AppFileSystem.defaultLayer),
Layer.provide(FSUtil.defaultLayer),
Layer.provide(Git.defaultLayer),
Layer.provide(Global.defaultLayer),
)