@ebay-dt/bonfire-node 0.2.0-alpha.3 → 0.2.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"local-prototype-lifecycle.js","sourceRoot":"","sources":["../../src/lifecycle/local-prototype-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { lstat, open, rename, rm, writeFile } from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport { join, relative, sep } from \"node:path\";\nimport {\n definePrototypeRef,\n getPrototypeUrl,\n LifecycleInputError,\n lifecycleFailure,\n lifecycleSuccess,\n parseCreatePrototypeInput,\n parseDuplicatePrototypeInput,\n parseEditPrototypeInput,\n parseBonfireIdentity,\n parsePrototypeCommandInput,\n parsePrototypeMetadata,\n slugifyPrototypeTitle,\n PrototypeRefError,\n type BranchPreparationValue,\n type CreatePrototypeInput,\n type CreatePrototypeValue,\n type DeletePrototypeValue,\n type DeploymentValue,\n type DeploymentWarningCode,\n type DirtyObservationValue,\n type DiscardPrototypeValue,\n type DuplicatePrototypeInput,\n type DuplicatePrototypeValue,\n type EditPrototypeInput,\n type EditPrototypeValue,\n parseGitModeSetting,\n type GitMode,\n type LifecycleErrorCode,\n type LifecycleResult,\n type BonfireIdentity,\n type PrototypeCommandInput,\n type SavePrototypeValue,\n type RepositorySummary,\n type ThemeRegistry,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n commitPath,\n discardPath,\n GitRepositoryError,\n pushBranch,\n type GitRepository,\n} from \"../git-repository.js\";\nimport { duplicatePrototype, PrototypeDuplicateError } from \"../duplicate.js\";\nimport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"../prototype-catalog.js\";\nimport { PrototypeScaffoldError, scaffoldPrototype } from \"../scaffold.js\";\nimport {\n createPrototypeLifecycleRuntime,\n type PrototypeLifecycleRuntimeContext,\n} from \"./runtime-context.js\";\nimport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"../prepare-prototype-files.js\";\nimport {\n cleanupOwnedDestination,\n validateOwnedDestination,\n type OwnedDestinationReceipt,\n} from \"../internal/owned-destination.js\";\nimport {\n RepositoryBusyError,\n withRepositoryOperation,\n} from \"./operation-gate.js\";\nimport {\n DeploymentProviderError,\n type DeploymentProvider,\n} from \"../deployment-provider.js\";\nimport {\n assertIdentityBranchReady,\n synchronizeIdentityBranch,\n} from \"./repository-synchronization.js\";\nimport { getRepositorySummary } from \"./repository-summary.js\";\n\ntype LifecycleMethod<Input, Value> = (\n identity: BonfireIdentity,\n input: Input,\n) => Promise<LifecycleResult<Value>>;\n\nexport type PrototypeLifecycle = {\n /** Declares whether this lifecycle enforces the selected Git mode. */\n readonly gitMode?: GitMode;\n prepareBranch(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<BranchPreparationValue>>;\n create: LifecycleMethod<CreatePrototypeInput, CreatePrototypeValue>;\n duplicate: LifecycleMethod<DuplicatePrototypeInput, DuplicatePrototypeValue>;\n edit: LifecycleMethod<EditPrototypeInput, EditPrototypeValue>;\n delete: LifecycleMethod<PrototypeCommandInput, DeletePrototypeValue>;\n getDirtyState: LifecycleMethod<PrototypeCommandInput, DirtyObservationValue>;\n getRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>>;\n checkRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>>;\n save: LifecycleMethod<PrototypeCommandInput, SavePrototypeValue>;\n discard: LifecycleMethod<PrototypeCommandInput, DiscardPrototypeValue>;\n deploy: LifecycleMethod<PrototypeCommandInput, DeploymentValue>;\n};\n\nexport type LocalPrototypeLifecycleOptions = {\n repositoryRoot: string;\n prototypeRoot?: string;\n remote?: string;\n primaryBranch?: string;\n automaticBranchSwitch?: \"enabled\" | \"disabled\";\n gitMode?: GitMode;\n commitIdentity?: {\n name: string;\n email: string;\n };\n catalog?: PrototypeCatalogLike;\n preparePrototypeFiles?: PreparePrototypeFiles;\n deploymentProvider?: DeploymentProvider;\n applicationId?: string;\n themeRegistry?: ThemeRegistry;\n};\n\ntype InternalLocalPrototypeLifecycleOptions = LocalPrototypeLifecycleOptions & {\n runtime?: PrototypeLifecycleRuntimeContext;\n};\n\nfunction repositoryRelativePath(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n const absolutePath = join(runtime.prototypeRoot, ref.login, ref.slug);\n return relative(runtime.repositoryRoot, absolutePath).split(sep).join(\"/\");\n}\n\nfunction destinationRef(identity: BonfireIdentity, title: string) {\n const slug = slugifyPrototypeTitle(title);\n if (slug === null)\n throw new PrototypeRefError(\"title\", \"must produce a slug\");\n return definePrototypeRef({ login: identity.login, slug });\n}\n\nclass PrototypeNotFoundError extends Error {}\nclass PrototypeOwnershipError extends Error {}\nclass PrototypeMetadataFileError extends Error {}\nclass DeploymentUnavailableError extends Error {}\n\nfunction metadataPath(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n return join(runtime.prototypeRoot, ref.login, ref.slug, \"metadata.json\");\n}\n\nasync function assertPrototypeDirectory(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n const paths = [\n runtime.prototypeRoot,\n join(runtime.prototypeRoot, ref.login),\n join(runtime.prototypeRoot, ref.login, ref.slug),\n ];\n\n try {\n for (const path of paths) {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isDirectory()) {\n throw new PrototypeMetadataFileError();\n }\n }\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function readMetadataDocument(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n themeRegistry?: ThemeRegistry,\n) {\n const path = metadataPath(runtime, ref);\n try {\n const file = await open(\n path,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n const source = await file.readFile(\"utf8\");\n const document: unknown = JSON.parse(source);\n parsePrototypeMetadata(document, { themeRegistry });\n if (\n typeof document !== \"object\" ||\n document === null ||\n Array.isArray(document)\n ) {\n throw new PrototypeMetadataFileError();\n }\n return { ...(document as Record<string, unknown>) };\n } finally {\n await file.close();\n }\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function removePrototypeDirectory(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n await assertPrototypeDirectory(runtime, ref);\n try {\n await rm(join(runtime.prototypeRoot, ref.login, ref.slug), {\n force: false,\n recursive: true,\n });\n } catch {\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function writeMetadataDocument(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n document: Record<string, unknown>,\n) {\n const path = metadataPath(runtime, ref);\n const temporaryPath = `${path}.${randomUUID()}.tmp`;\n\n try {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isFile()) {\n throw new PrototypeMetadataFileError();\n }\n await writeFile(temporaryPath, `${JSON.stringify(document, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n await rename(temporaryPath, path);\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n } finally {\n await rm(temporaryPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function mergeIdentityBranchToPrimary(\n repository: GitRepository,\n options: {\n branch: string;\n primaryBranch: string;\n remote: string;\n },\n) {\n if (options.branch === options.primaryBranch) return;\n\n const hasRemote = (await repository.remotes()).some(\n (remote) => remote.name === options.remote,\n );\n if (!hasRemote) return;\n\n await repository.checkout([options.primaryBranch]);\n try {\n await repository.merge([\n options.branch,\n \"--no-ff\",\n \"-m\",\n `merge: ${options.branch}`,\n ]);\n await repository.push(options.remote, options.primaryBranch);\n } finally {\n await repository.checkout([options.branch]);\n }\n}\n\nfunction mapError(error: unknown): LifecycleErrorCode {\n if (error instanceof PrototypeNotFoundError) return \"not-found\";\n if (error instanceof PrototypeOwnershipError) return \"forbidden\";\n if (error instanceof PrototypeMetadataFileError) return \"filesystem-failure\";\n if (error instanceof RepositoryBusyError) return \"repository-busy\";\n if (\n error instanceof PrototypeRefError ||\n error instanceof LifecycleInputError\n ) {\n return \"invalid-input\";\n }\n if (error instanceof GitRepositoryError) {\n if (error.kind === \"timeout\") return \"timeout\";\n if (error.kind === \"conflict\") return \"working-tree-conflict\";\n if (error.kind === \"invalid-configuration\") return \"unexpected-failure\";\n return \"git-failure\";\n }\n if (error instanceof PrototypeScaffoldError) {\n if (error.kind === \"collision\") return \"already-exists\";\n if (error.kind === \"invalid-input\") return \"invalid-input\";\n return \"filesystem-failure\";\n }\n if (error instanceof PrototypeDuplicateError) {\n if (error.kind === \"source-not-found\") return \"not-found\";\n if (error.kind === \"collision\") return \"already-exists\";\n if (error.kind === \"invalid-source\") return \"invalid-input\";\n return \"filesystem-failure\";\n }\n if (error instanceof DeploymentUnavailableError) {\n return \"deployment-unavailable\";\n }\n if (error instanceof DeploymentProviderError) {\n return error.kind === \"timeout\" ? \"timeout\" : \"deployment-failure\";\n }\n return \"unexpected-failure\";\n}\n\nfunction resultFrom<Value>(\n operation: () => Promise<Value>,\n): Promise<LifecycleResult<Value>> {\n return operation()\n .then(lifecycleSuccess)\n .catch((error: unknown) => lifecycleFailure(mapError(error)));\n}\n\nexport class LocalPrototypeLifecycle implements PrototypeLifecycle {\n readonly #runtime: PrototypeLifecycleRuntimeContext;\n readonly gitMode: GitMode;\n readonly #catalog: PrototypeCatalogLike;\n readonly #repository: GitRepository;\n readonly #preparePrototypeFiles: PreparePrototypeFiles;\n readonly #deploymentProvider?: DeploymentProvider;\n readonly #applicationId?: string;\n readonly #themeRegistry?: ThemeRegistry;\n\n constructor(options: LocalPrototypeLifecycleOptions) {\n const internalOptions = options as InternalLocalPrototypeLifecycleOptions;\n const runtime =\n internalOptions.runtime ?? createPrototypeLifecycleRuntime(internalOptions);\n this.#runtime = {\n ...runtime,\n gitMode: parseGitModeSetting(runtime.gitMode),\n };\n this.gitMode = this.#runtime.gitMode;\n this.#themeRegistry = options.themeRegistry;\n this.#catalog =\n internalOptions.catalog ??\n new PrototypeCatalog({\n ...this.#runtime,\n themeRegistry: this.#themeRegistry,\n });\n this.#repository = this.#runtime.gitRepository;\n this.#preparePrototypeFiles =\n internalOptions.preparePrototypeFiles ?? (() => undefined);\n this.#deploymentProvider = internalOptions.deploymentProvider;\n this.#applicationId = internalOptions.applicationId;\n if (\n this.#deploymentProvider &&\n (typeof this.#applicationId !== \"string\" ||\n this.#applicationId.length === 0)\n ) {\n throw new TypeError(\n \"applicationId must be provided when deploymentProvider is configured\",\n );\n }\n }\n\n async #verifiedIdentity(identity: BonfireIdentity) {\n return parseBonfireIdentity(identity);\n }\n\n async #currentBranch() {\n const branch = await this.#repository.currentBranch();\n if (branch === \"HEAD\" || branch.length === 0) {\n throw new GitRepositoryError(\"conflict\", \"current-branch\");\n }\n return branch;\n }\n\n async #ownedPrototype(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ) {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n if (normalizedInput.ref.login !== verifiedIdentity.login) {\n throw new PrototypeOwnershipError();\n }\n const summary = await this.#catalog.getSummary(normalizedInput.ref);\n if (!summary) {\n throw new PrototypeNotFoundError();\n }\n\n return {\n ref: normalizedInput.ref,\n path: repositoryRelativePath(this.#runtime, normalizedInput.ref),\n summary,\n };\n }\n\n async #prepareMutationBranch(login: string) {\n await assertIdentityBranchReady(this.#repository, login);\n return login;\n }\n\n async #prepareDestination(\n receipt: OwnedDestinationReceipt,\n expectedFiles: readonly string[],\n request: PreparePrototypeFilesRequest,\n ) {\n try {\n const frozenRequest = Object.freeze({\n ...request,\n ref: Object.freeze({ ...request.ref }),\n identity: Object.freeze({ ...request.identity }),\n ...(request.operation === \"duplicate\"\n ? { source: Object.freeze({ ...request.source }) }\n : {}),\n }) as PreparePrototypeFilesRequest;\n await this.#preparePrototypeFiles(frozenRequest);\n await validateOwnedDestination(\n receipt,\n expectedFiles,\n request.ref,\n this.#themeRegistry,\n );\n } catch {\n try {\n await cleanupOwnedDestination(receipt);\n } catch {\n // The failure remains a finite filesystem failure without retrying cleanup.\n }\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n }\n\n async prepareBranch(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<BranchPreparationValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (\n this.#runtime.gitMode === \"manual\" ||\n this.#runtime.automaticBranchSwitch === \"disabled\"\n ) {\n await this.#currentBranch();\n return { status: \"disabled\" } satisfies BranchPreparationValue;\n }\n\n const synchronization = await synchronizeIdentityBranch(\n this.#repository,\n {\n identityBranch: verifiedIdentity.login,\n primaryBranch: this.#runtime.primaryBranch,\n remote: this.#runtime.remote,\n },\n );\n if (synchronization.status !== \"synchronized\") {\n return {\n status: synchronization.status,\n reason: synchronization.reason,\n ...(synchronization.affectedPaths.length > 0\n ? { affectedPaths: synchronization.affectedPaths }\n : {}),\n } satisfies BranchPreparationValue;\n }\n return { status: \"ready\" } satisfies BranchPreparationValue;\n },\n );\n });\n }\n\n async create(\n identity: BonfireIdentity,\n input: CreatePrototypeInput,\n ): Promise<LifecycleResult<CreatePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseCreatePrototypeInput(\n input,\n this.#themeRegistry,\n );\n const ref = destinationRef(verifiedIdentity, normalizedInput.title);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (await this.#catalog.getSummary(ref)) {\n throw new PrototypeScaffoldError(\"collision\");\n }\n\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n const prepared = await scaffoldPrototype({\n paths: this.#runtime,\n ref,\n title: normalizedInput.title,\n description: normalizedInput.description,\n authorName: verifiedIdentity.name,\n theme: normalizedInput.theme,\n themeRegistry: this.#themeRegistry,\n });\n await this.#prepareDestination(\n prepared.receipt,\n prepared.expectedFiles,\n {\n operation: \"create\",\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n prototypePath: prepared.destination,\n ref,\n identity: verifiedIdentity,\n title: normalizedInput.title,\n description: normalizedInput.description,\n },\n );\n if (branch === undefined) {\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: \"manual\",\n } satisfies CreatePrototypeValue;\n }\n\n await commitPath(\n this.#repository,\n repositoryRelativePath(this.#runtime, ref),\n `init: ${ref.slug}`,\n );\n const push = await pushBranch(\n this.#repository,\n this.#runtime.remote,\n branch,\n );\n\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: push.remoteStatus,\n } satisfies CreatePrototypeValue;\n },\n );\n });\n }\n\n async edit(\n identity: BonfireIdentity,\n input: EditPrototypeInput,\n ): Promise<LifecycleResult<EditPrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseEditPrototypeInput(\n input,\n this.#themeRegistry,\n );\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(verifiedIdentity, {\n ref: normalizedInput.ref,\n });\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n await assertPrototypeDirectory(this.#runtime, ref);\n const document = await readMetadataDocument(\n this.#runtime,\n ref,\n this.#themeRegistry,\n );\n const metadata = parsePrototypeMetadata(document, {\n themeRegistry: this.#themeRegistry,\n });\n if (metadata.authorLogin !== ref.login) {\n throw new PrototypeNotFoundError();\n }\n\n await writeMetadataDocument(this.#runtime, ref, {\n ...document,\n title: normalizedInput.title,\n description: normalizedInput.description,\n updatedAt: new Date().toISOString(),\n ...(normalizedInput.theme === undefined\n ? {}\n : { theme: normalizedInput.theme }),\n });\n if (branch !== undefined) {\n await commitPath(this.#repository, path, `edit: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n }\n\n return { edited: true, ref } satisfies EditPrototypeValue;\n },\n );\n });\n }\n\n async delete(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DeletePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n normalizedInput,\n );\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n await removePrototypeDirectory(this.#runtime, ref);\n if (branch !== undefined) {\n await commitPath(this.#repository, path, `delete: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n }\n\n return { deleted: true, ref } satisfies DeletePrototypeValue;\n },\n );\n });\n }\n\n async getDirtyState(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DirtyObservationValue>> {\n return resultFrom(async () => {\n const { path, summary } = await this.#ownedPrototype(identity, input);\n const status = await this.#repository.status([path]);\n return {\n status: status.files.length > 0 ? \"dirty\" : \"clean\",\n ...(summary.previewUrl !== undefined\n ? { previewUrl: summary.previewUrl }\n : {}),\n } satisfies DirtyObservationValue;\n });\n }\n\n async getRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return getRepositorySummary({\n repository: this.#repository,\n catalog: this.#catalog,\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n identity: verifiedIdentity,\n mode: this.#runtime.gitMode,\n remote: this.#runtime.remote,\n primaryBranch: this.#runtime.primaryBranch,\n });\n });\n }\n\n async checkRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return getRepositorySummary({\n repository: this.#repository,\n catalog: this.#catalog,\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n identity: verifiedIdentity,\n mode: this.#runtime.gitMode,\n remote: this.#runtime.remote,\n primaryBranch: this.#runtime.primaryBranch,\n refresh: true,\n });\n });\n }\n\n async deploy(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DeploymentValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n if (!this.#deploymentProvider) {\n throw new DeploymentUnavailableError();\n }\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n normalizedInput,\n );\n const branch = await this.#prepareMutationBranch(\n verifiedIdentity.login,\n );\n await assertPrototypeDirectory(this.#runtime, ref);\n const document = await readMetadataDocument(\n this.#runtime,\n ref,\n this.#themeRegistry,\n );\n const metadata = parsePrototypeMetadata(document, {\n themeRegistry: this.#themeRegistry,\n });\n if (metadata.authorLogin !== ref.login) {\n throw new PrototypeNotFoundError();\n }\n await commitPath(this.#repository, path, `deploy: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n\n const deployment = await this.#deploymentProvider!.deploy({\n applicationId: this.#applicationId!,\n login: verifiedIdentity.login,\n });\n const previewUrl = new URL(\n getPrototypeUrl(ref).slice(1),\n `${deployment.url.replace(/\\/+$/, \"\")}/`,\n ).toString();\n\n let warning: DeploymentWarningCode | undefined;\n try {\n await writeMetadataDocument(this.#runtime, ref, {\n ...document,\n previewUrl,\n updatedAt: new Date().toISOString(),\n });\n await commitPath(\n this.#repository,\n path,\n `deploy: ${ref.slug} (metadata)`,\n );\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n } catch {\n warning = \"metadata-persistence-failed\";\n }\n\n if (warning === undefined) {\n try {\n await mergeIdentityBranchToPrimary(this.#repository, {\n branch,\n primaryBranch: this.#runtime.primaryBranch,\n remote: this.#runtime.remote,\n });\n } catch {\n warning = \"primary-merge-failed\";\n }\n }\n\n return {\n deployed: true,\n ref,\n previewUrl,\n deploymentId: deployment.deploymentId,\n readyState: deployment.readyState,\n warning,\n } satisfies DeploymentValue;\n },\n );\n });\n }\n\n async save(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<SavePrototypeValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n input,\n );\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n await this.#prepareMutationBranch(verifiedIdentity.login);\n await commitPath(this.#repository, path, `save: ${ref.slug}`);\n await pushBranch(\n this.#repository,\n this.#runtime.remote,\n verifiedIdentity.login,\n );\n return { saved: true } satisfies SavePrototypeValue;\n },\n );\n });\n }\n\n async discard(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DiscardPrototypeValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const { path } = await this.#ownedPrototype(\n verifiedIdentity,\n input,\n );\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n await discardPath(this.#repository, path);\n return { discarded: true } satisfies DiscardPrototypeValue;\n },\n );\n });\n }\n\n async duplicate(\n identity: BonfireIdentity,\n input: DuplicatePrototypeInput,\n ): Promise<LifecycleResult<DuplicatePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseDuplicatePrototypeInput(input);\n if (!(await this.#catalog.getSummary(normalizedInput.source))) {\n throw new PrototypeDuplicateError(\"source-not-found\");\n }\n const ref = destinationRef(verifiedIdentity, normalizedInput.title);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (await this.#catalog.getSummary(ref)) {\n throw new PrototypeDuplicateError(\"collision\");\n }\n\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n const prepared = await duplicatePrototype({\n paths: this.#runtime,\n source: normalizedInput.source,\n destination: ref,\n title: normalizedInput.title,\n description: normalizedInput.description,\n authorName: verifiedIdentity.name,\n themeRegistry: this.#themeRegistry,\n });\n await this.#prepareDestination(\n prepared.receipt,\n prepared.expectedFiles,\n {\n operation: \"duplicate\",\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n prototypePath: prepared.destination,\n ref,\n source: normalizedInput.source,\n identity: verifiedIdentity,\n title: normalizedInput.title,\n description: normalizedInput.description,\n },\n );\n if (branch === undefined) {\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: \"manual\",\n } satisfies DuplicatePrototypeValue;\n }\n\n await commitPath(\n this.#repository,\n repositoryRelativePath(this.#runtime, ref),\n `init: ${ref.slug}`,\n );\n const push = await pushBranch(\n this.#repository,\n this.#runtime.remote,\n branch,\n );\n\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: push.remoteStatus,\n } satisfies DuplicatePrototypeValue;\n },\n );\n });\n }\n}\n"]}
1
+ {"version":3,"file":"local-prototype-lifecycle.js","sourceRoot":"","sources":["../../src/lifecycle/local-prototype-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { lstat, open, rename, rm, writeFile } from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport { join, relative, sep } from \"node:path\";\nimport {\n definePrototypeRef,\n getPrototypeUrl,\n LifecycleInputError,\n lifecycleFailure,\n lifecycleSuccess,\n parseCreatePrototypeInput,\n parseDuplicatePrototypeInput,\n parseEditPrototypeInput,\n parseBonfireIdentity,\n parsePrototypeCommandInput,\n parsePrototypeMetadata,\n slugifyPrototypeTitle,\n PrototypeRefError,\n type BranchPreparationValue,\n type CreatePrototypeInput,\n type CreatePrototypeValue,\n type DeletePrototypeValue,\n type DeploymentValue,\n type DeploymentWarningCode,\n type DirtyObservationValue,\n type DiscardPrototypeValue,\n type DuplicatePrototypeInput,\n type DuplicatePrototypeValue,\n type EditPrototypeInput,\n type EditPrototypeValue,\n parseGitModeSetting,\n type GitMode,\n type LifecycleErrorCode,\n type LifecycleResult,\n type BonfireIdentity,\n type PrototypeCommandInput,\n type SavePrototypeValue,\n type RepositorySummary,\n type ThemeRegistry,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n commitPath,\n discardPath,\n GitRepositoryError,\n pushBranch,\n type GitRepository,\n} from \"../git-repository.js\";\nimport { duplicatePrototype, PrototypeDuplicateError } from \"../duplicate.js\";\nimport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"../prototype-catalog.js\";\nimport { PrototypeScaffoldError, scaffoldPrototype } from \"../scaffold.js\";\nimport {\n createPrototypeLifecycleRuntime,\n type PrototypeLifecycleRuntimeContext,\n} from \"./runtime-context.js\";\nimport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"../prepare-prototype-files.js\";\nimport {\n cleanupOwnedDestination,\n validateOwnedDestination,\n type OwnedDestinationReceipt,\n} from \"../internal/owned-destination.js\";\nimport {\n RepositoryBusyError,\n withRepositoryOperation,\n} from \"./operation-gate.js\";\nimport {\n DeploymentProviderError,\n type DeploymentProvider,\n} from \"../deployment-provider.js\";\nimport {\n assertIdentityBranchReady,\n synchronizeIdentityBranch,\n} from \"./repository-synchronization.js\";\nimport { getRepositorySummary } from \"./repository-summary.js\";\n\ntype LifecycleMethod<Input, Value> = (\n identity: BonfireIdentity,\n input: Input,\n) => Promise<LifecycleResult<Value>>;\n\nexport type PrototypeLifecycle = {\n /** Declares whether this lifecycle enforces the selected Git mode. */\n readonly gitMode?: GitMode;\n prepareBranch(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<BranchPreparationValue>>;\n create: LifecycleMethod<CreatePrototypeInput, CreatePrototypeValue>;\n duplicate: LifecycleMethod<DuplicatePrototypeInput, DuplicatePrototypeValue>;\n edit: LifecycleMethod<EditPrototypeInput, EditPrototypeValue>;\n delete: LifecycleMethod<PrototypeCommandInput, DeletePrototypeValue>;\n getDirtyState: LifecycleMethod<PrototypeCommandInput, DirtyObservationValue>;\n getRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>>;\n checkRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>>;\n save: LifecycleMethod<PrototypeCommandInput, SavePrototypeValue>;\n discard: LifecycleMethod<PrototypeCommandInput, DiscardPrototypeValue>;\n deploy: LifecycleMethod<PrototypeCommandInput, DeploymentValue>;\n};\n\nexport type LocalPrototypeLifecycleOptions = {\n repositoryRoot: string;\n prototypeRoot?: string;\n remote?: string;\n primaryBranch?: string;\n automaticBranchSwitch?: \"enabled\" | \"disabled\";\n gitMode?: GitMode;\n commitIdentity?: {\n name: string;\n email: string;\n };\n catalog?: PrototypeCatalogLike;\n preparePrototypeFiles?: PreparePrototypeFiles;\n deploymentProvider?: DeploymentProvider;\n applicationId?: string;\n themeRegistry?: ThemeRegistry;\n};\n\ntype InternalLocalPrototypeLifecycleOptions = LocalPrototypeLifecycleOptions & {\n runtime?: PrototypeLifecycleRuntimeContext;\n};\n\nfunction repositoryRelativePath(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n const absolutePath = join(runtime.prototypeRoot, ref.login, ref.slug);\n return relative(runtime.repositoryRoot, absolutePath).split(sep).join(\"/\");\n}\n\nfunction destinationRef(identity: BonfireIdentity, title: string) {\n const slug = slugifyPrototypeTitle(title);\n if (slug === null)\n throw new PrototypeRefError(\"title\", \"must produce a slug\");\n return definePrototypeRef({ login: identity.login, slug });\n}\n\nclass PrototypeNotFoundError extends Error {}\nclass PrototypeOwnershipError extends Error {}\nclass PrototypeMetadataFileError extends Error {}\nclass DeploymentUnavailableError extends Error {}\n\nfunction metadataPath(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n return join(runtime.prototypeRoot, ref.login, ref.slug, \"metadata.json\");\n}\n\nasync function assertPrototypeDirectory(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n const paths = [\n runtime.prototypeRoot,\n join(runtime.prototypeRoot, ref.login),\n join(runtime.prototypeRoot, ref.login, ref.slug),\n ];\n\n try {\n for (const path of paths) {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isDirectory()) {\n throw new PrototypeMetadataFileError();\n }\n }\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function readMetadataDocument(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n themeRegistry?: ThemeRegistry,\n) {\n const path = metadataPath(runtime, ref);\n try {\n const file = await open(\n path,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n const source = await file.readFile(\"utf8\");\n const document: unknown = JSON.parse(source);\n parsePrototypeMetadata(document, { themeRegistry });\n if (\n typeof document !== \"object\" ||\n document === null ||\n Array.isArray(document)\n ) {\n throw new PrototypeMetadataFileError();\n }\n return { ...(document as Record<string, unknown>) };\n } finally {\n await file.close();\n }\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function removePrototypeDirectory(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n) {\n await assertPrototypeDirectory(runtime, ref);\n try {\n await rm(join(runtime.prototypeRoot, ref.login, ref.slug), {\n force: false,\n recursive: true,\n });\n } catch {\n throw new PrototypeMetadataFileError();\n }\n}\n\nasync function writeMetadataDocument(\n runtime: PrototypeLifecycleRuntimeContext,\n ref: { login: string; slug: string },\n document: Record<string, unknown>,\n) {\n const path = metadataPath(runtime, ref);\n const temporaryPath = `${path}.${randomUUID()}.tmp`;\n\n try {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isFile()) {\n throw new PrototypeMetadataFileError();\n }\n await writeFile(temporaryPath, `${JSON.stringify(document, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n await rename(temporaryPath, path);\n } catch (error) {\n if (error instanceof PrototypeMetadataFileError) throw error;\n throw new PrototypeMetadataFileError();\n } finally {\n await rm(temporaryPath, { force: true }).catch(() => undefined);\n }\n}\n\nasync function mergeIdentityBranchToPrimary(\n repository: GitRepository,\n options: {\n branch: string;\n primaryBranch: string;\n remote: string;\n },\n) {\n if (options.branch === options.primaryBranch) return;\n\n const hasRemote = (await repository.remotes()).some(\n (remote) => remote.name === options.remote,\n );\n if (!hasRemote) return;\n\n await repository.checkout([options.primaryBranch]);\n try {\n await repository.merge([\n options.branch,\n \"--no-ff\",\n \"-m\",\n `merge: ${options.branch}`,\n ]);\n await repository.push(options.remote, options.primaryBranch);\n } finally {\n await repository.checkout([options.branch]);\n }\n}\n\nfunction mapError(error: unknown): LifecycleErrorCode {\n if (error instanceof PrototypeNotFoundError) return \"not-found\";\n if (error instanceof PrototypeOwnershipError) return \"forbidden\";\n if (error instanceof PrototypeMetadataFileError) return \"filesystem-failure\";\n if (error instanceof RepositoryBusyError) return \"repository-busy\";\n if (\n error instanceof PrototypeRefError ||\n error instanceof LifecycleInputError\n ) {\n return \"invalid-input\";\n }\n if (error instanceof GitRepositoryError) {\n if (error.kind === \"timeout\") return \"timeout\";\n if (error.kind === \"conflict\") return \"working-tree-conflict\";\n if (error.kind === \"invalid-configuration\") return \"unexpected-failure\";\n return \"git-failure\";\n }\n if (error instanceof PrototypeScaffoldError) {\n if (error.kind === \"collision\") return \"already-exists\";\n if (error.kind === \"invalid-input\") return \"invalid-input\";\n return \"filesystem-failure\";\n }\n if (error instanceof PrototypeDuplicateError) {\n if (error.kind === \"source-not-found\") return \"not-found\";\n if (error.kind === \"collision\") return \"already-exists\";\n if (error.kind === \"invalid-source\") return \"invalid-input\";\n return \"filesystem-failure\";\n }\n if (error instanceof DeploymentUnavailableError) {\n return \"deployment-unavailable\";\n }\n if (error instanceof DeploymentProviderError) {\n return error.kind === \"timeout\" ? \"timeout\" : \"deployment-failure\";\n }\n return \"unexpected-failure\";\n}\n\nfunction resultFrom<Value>(\n operation: () => Promise<Value>,\n): Promise<LifecycleResult<Value>> {\n return operation()\n .then(lifecycleSuccess)\n .catch((error: unknown) => lifecycleFailure(mapError(error)));\n}\n\nexport class LocalPrototypeLifecycle implements PrototypeLifecycle {\n readonly #runtime: PrototypeLifecycleRuntimeContext;\n readonly gitMode: GitMode;\n readonly #catalog: PrototypeCatalogLike;\n readonly #repository: GitRepository;\n readonly #preparePrototypeFiles: PreparePrototypeFiles;\n readonly #deploymentProvider?: DeploymentProvider;\n readonly #applicationId?: string;\n readonly #themeRegistry?: ThemeRegistry;\n #restartRequired = false;\n\n constructor(options: LocalPrototypeLifecycleOptions) {\n const internalOptions = options as InternalLocalPrototypeLifecycleOptions;\n const runtime =\n internalOptions.runtime ?? createPrototypeLifecycleRuntime(internalOptions);\n this.#runtime = {\n ...runtime,\n gitMode: parseGitModeSetting(runtime.gitMode),\n };\n this.gitMode = this.#runtime.gitMode;\n this.#themeRegistry = options.themeRegistry;\n this.#catalog =\n internalOptions.catalog ??\n new PrototypeCatalog({\n ...this.#runtime,\n themeRegistry: this.#themeRegistry,\n });\n this.#repository = this.#runtime.gitRepository;\n this.#preparePrototypeFiles =\n internalOptions.preparePrototypeFiles ?? (() => undefined);\n this.#deploymentProvider = internalOptions.deploymentProvider;\n this.#applicationId = internalOptions.applicationId;\n if (\n this.#deploymentProvider &&\n (typeof this.#applicationId !== \"string\" ||\n this.#applicationId.length === 0)\n ) {\n throw new TypeError(\n \"applicationId must be provided when deploymentProvider is configured\",\n );\n }\n }\n\n async #verifiedIdentity(identity: BonfireIdentity) {\n return parseBonfireIdentity(identity);\n }\n\n async #currentBranch() {\n const branch = await this.#repository.currentBranch();\n if (branch === \"HEAD\" || branch.length === 0) {\n throw new GitRepositoryError(\"conflict\", \"current-branch\");\n }\n return branch;\n }\n\n async #ownedPrototype(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ) {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n if (normalizedInput.ref.login !== verifiedIdentity.login) {\n throw new PrototypeOwnershipError();\n }\n const summary = await this.#catalog.getSummary(normalizedInput.ref);\n if (!summary) {\n throw new PrototypeNotFoundError();\n }\n\n return {\n ref: normalizedInput.ref,\n path: repositoryRelativePath(this.#runtime, normalizedInput.ref),\n summary,\n };\n }\n\n async #prepareMutationBranch(login: string) {\n await assertIdentityBranchReady(this.#repository, login);\n return login;\n }\n\n async #prepareDestination(\n receipt: OwnedDestinationReceipt,\n expectedFiles: readonly string[],\n request: PreparePrototypeFilesRequest,\n ) {\n try {\n const frozenRequest = Object.freeze({\n ...request,\n ref: Object.freeze({ ...request.ref }),\n identity: Object.freeze({ ...request.identity }),\n ...(request.operation === \"duplicate\"\n ? { source: Object.freeze({ ...request.source }) }\n : {}),\n }) as PreparePrototypeFilesRequest;\n await this.#preparePrototypeFiles(frozenRequest);\n await validateOwnedDestination(\n receipt,\n expectedFiles,\n request.ref,\n this.#themeRegistry,\n );\n } catch {\n try {\n await cleanupOwnedDestination(receipt);\n } catch {\n // The failure remains a finite filesystem failure without retrying cleanup.\n }\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n }\n\n async prepareBranch(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<BranchPreparationValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (\n this.#runtime.gitMode === \"manual\" ||\n this.#runtime.automaticBranchSwitch === \"disabled\"\n ) {\n await this.#currentBranch();\n return { status: \"disabled\" } satisfies BranchPreparationValue;\n }\n\n const synchronization = await synchronizeIdentityBranch(\n this.#repository,\n {\n identityBranch: verifiedIdentity.login,\n primaryBranch: this.#runtime.primaryBranch,\n remote: this.#runtime.remote,\n managedPaths: this.#runtime.managedRepositoryPaths,\n },\n );\n if (synchronization.status !== \"synchronized\") {\n return {\n status: synchronization.status,\n reason: synchronization.reason,\n ...(synchronization.affectedPaths.length > 0\n ? { affectedPaths: synchronization.affectedPaths }\n : {}),\n } satisfies BranchPreparationValue;\n }\n if (\n synchronization.affectedPaths.some((path) =>\n this.#runtime.managedRepositoryPaths.includes(path),\n )\n ) {\n this.#restartRequired = true;\n }\n return {\n status: \"ready\",\n ...(synchronization.affectedPaths.length > 0\n ? { affectedPaths: synchronization.affectedPaths }\n : {}),\n } satisfies BranchPreparationValue;\n },\n );\n });\n }\n\n async create(\n identity: BonfireIdentity,\n input: CreatePrototypeInput,\n ): Promise<LifecycleResult<CreatePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseCreatePrototypeInput(\n input,\n this.#themeRegistry,\n );\n const ref = destinationRef(verifiedIdentity, normalizedInput.title);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (await this.#catalog.getSummary(ref)) {\n throw new PrototypeScaffoldError(\"collision\");\n }\n\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n const prepared = await scaffoldPrototype({\n paths: this.#runtime,\n ref,\n title: normalizedInput.title,\n description: normalizedInput.description,\n authorName: verifiedIdentity.name,\n theme: normalizedInput.theme,\n themeRegistry: this.#themeRegistry,\n });\n await this.#prepareDestination(\n prepared.receipt,\n prepared.expectedFiles,\n {\n operation: \"create\",\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n prototypePath: prepared.destination,\n ref,\n identity: verifiedIdentity,\n title: normalizedInput.title,\n description: normalizedInput.description,\n },\n );\n if (branch === undefined) {\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: \"manual\",\n } satisfies CreatePrototypeValue;\n }\n\n await commitPath(\n this.#repository,\n repositoryRelativePath(this.#runtime, ref),\n `init: ${ref.slug}`,\n );\n const push = await pushBranch(\n this.#repository,\n this.#runtime.remote,\n branch,\n );\n\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: push.remoteStatus,\n } satisfies CreatePrototypeValue;\n },\n );\n });\n }\n\n async edit(\n identity: BonfireIdentity,\n input: EditPrototypeInput,\n ): Promise<LifecycleResult<EditPrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseEditPrototypeInput(\n input,\n this.#themeRegistry,\n );\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(verifiedIdentity, {\n ref: normalizedInput.ref,\n });\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n await assertPrototypeDirectory(this.#runtime, ref);\n const document = await readMetadataDocument(\n this.#runtime,\n ref,\n this.#themeRegistry,\n );\n const metadata = parsePrototypeMetadata(document, {\n themeRegistry: this.#themeRegistry,\n });\n if (metadata.authorLogin !== ref.login) {\n throw new PrototypeNotFoundError();\n }\n\n await writeMetadataDocument(this.#runtime, ref, {\n ...document,\n title: normalizedInput.title,\n description: normalizedInput.description,\n updatedAt: new Date().toISOString(),\n ...(normalizedInput.theme === undefined\n ? {}\n : { theme: normalizedInput.theme }),\n });\n if (branch !== undefined) {\n await commitPath(this.#repository, path, `edit: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n }\n\n return { edited: true, ref } satisfies EditPrototypeValue;\n },\n );\n });\n }\n\n async delete(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DeletePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n normalizedInput,\n );\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n await removePrototypeDirectory(this.#runtime, ref);\n if (branch !== undefined) {\n await commitPath(this.#repository, path, `delete: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n }\n\n return { deleted: true, ref } satisfies DeletePrototypeValue;\n },\n );\n });\n }\n\n async getDirtyState(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DirtyObservationValue>> {\n return resultFrom(async () => {\n const { path, summary } = await this.#ownedPrototype(identity, input);\n const status = await this.#repository.status([path]);\n return {\n status: status.files.length > 0 ? \"dirty\" : \"clean\",\n ...(summary.previewUrl !== undefined\n ? { previewUrl: summary.previewUrl }\n : {}),\n } satisfies DirtyObservationValue;\n });\n }\n\n async getRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return getRepositorySummary({\n repository: this.#repository,\n catalog: this.#catalog,\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n identity: verifiedIdentity,\n mode: this.#runtime.gitMode,\n remote: this.#runtime.remote,\n primaryBranch: this.#runtime.primaryBranch,\n restartRequired: this.#restartRequired,\n });\n });\n }\n\n async checkRepositorySummary(\n identity: BonfireIdentity,\n ): Promise<LifecycleResult<RepositorySummary>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n return getRepositorySummary({\n repository: this.#repository,\n catalog: this.#catalog,\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n identity: verifiedIdentity,\n mode: this.#runtime.gitMode,\n remote: this.#runtime.remote,\n primaryBranch: this.#runtime.primaryBranch,\n restartRequired: this.#restartRequired,\n refresh: true,\n });\n });\n }\n\n async deploy(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DeploymentValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parsePrototypeCommandInput(input);\n if (!this.#deploymentProvider) {\n throw new DeploymentUnavailableError();\n }\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n normalizedInput,\n );\n const branch = await this.#prepareMutationBranch(\n verifiedIdentity.login,\n );\n await assertPrototypeDirectory(this.#runtime, ref);\n const document = await readMetadataDocument(\n this.#runtime,\n ref,\n this.#themeRegistry,\n );\n const metadata = parsePrototypeMetadata(document, {\n themeRegistry: this.#themeRegistry,\n });\n if (metadata.authorLogin !== ref.login) {\n throw new PrototypeNotFoundError();\n }\n await commitPath(this.#repository, path, `deploy: ${ref.slug}`);\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n\n const deployment = await this.#deploymentProvider!.deploy({\n applicationId: this.#applicationId!,\n login: verifiedIdentity.login,\n });\n const previewUrl = new URL(\n getPrototypeUrl(ref).slice(1),\n `${deployment.url.replace(/\\/+$/, \"\")}/`,\n ).toString();\n\n let warning: DeploymentWarningCode | undefined;\n try {\n await writeMetadataDocument(this.#runtime, ref, {\n ...document,\n previewUrl,\n updatedAt: new Date().toISOString(),\n });\n await commitPath(\n this.#repository,\n path,\n `deploy: ${ref.slug} (metadata)`,\n );\n await pushBranch(this.#repository, this.#runtime.remote, branch);\n } catch {\n warning = \"metadata-persistence-failed\";\n }\n\n if (warning === undefined) {\n try {\n await mergeIdentityBranchToPrimary(this.#repository, {\n branch,\n primaryBranch: this.#runtime.primaryBranch,\n remote: this.#runtime.remote,\n });\n } catch {\n warning = \"primary-merge-failed\";\n }\n }\n\n return {\n deployed: true,\n ref,\n previewUrl,\n deploymentId: deployment.deploymentId,\n readyState: deployment.readyState,\n warning,\n } satisfies DeploymentValue;\n },\n );\n });\n }\n\n async save(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<SavePrototypeValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const { ref, path } = await this.#ownedPrototype(\n verifiedIdentity,\n input,\n );\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n await this.#prepareMutationBranch(verifiedIdentity.login);\n await commitPath(this.#repository, path, `save: ${ref.slug}`);\n await pushBranch(\n this.#repository,\n this.#runtime.remote,\n verifiedIdentity.login,\n );\n return { saved: true } satisfies SavePrototypeValue;\n },\n );\n });\n }\n\n async discard(\n identity: BonfireIdentity,\n input: PrototypeCommandInput,\n ): Promise<LifecycleResult<DiscardPrototypeValue>> {\n if (this.#runtime.gitMode === \"manual\") {\n return lifecycleFailure(\"forbidden\");\n }\n\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const { path } = await this.#ownedPrototype(\n verifiedIdentity,\n input,\n );\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n await discardPath(this.#repository, path);\n return { discarded: true } satisfies DiscardPrototypeValue;\n },\n );\n });\n }\n\n async duplicate(\n identity: BonfireIdentity,\n input: DuplicatePrototypeInput,\n ): Promise<LifecycleResult<DuplicatePrototypeValue>> {\n return resultFrom(async () => {\n const verifiedIdentity = await this.#verifiedIdentity(identity);\n const normalizedInput = parseDuplicatePrototypeInput(input);\n if (!(await this.#catalog.getSummary(normalizedInput.source))) {\n throw new PrototypeDuplicateError(\"source-not-found\");\n }\n const ref = destinationRef(verifiedIdentity, normalizedInput.title);\n\n return withRepositoryOperation(\n this.#runtime.repositoryRealPath,\n async () => {\n if (await this.#catalog.getSummary(ref)) {\n throw new PrototypeDuplicateError(\"collision\");\n }\n\n const branch =\n this.#runtime.gitMode === \"managed\"\n ? await this.#prepareMutationBranch(verifiedIdentity.login)\n : undefined;\n const prepared = await duplicatePrototype({\n paths: this.#runtime,\n source: normalizedInput.source,\n destination: ref,\n title: normalizedInput.title,\n description: normalizedInput.description,\n authorName: verifiedIdentity.name,\n themeRegistry: this.#themeRegistry,\n });\n await this.#prepareDestination(\n prepared.receipt,\n prepared.expectedFiles,\n {\n operation: \"duplicate\",\n repositoryRoot: this.#runtime.repositoryRoot,\n prototypeRoot: this.#runtime.prototypeRoot,\n prototypePath: prepared.destination,\n ref,\n source: normalizedInput.source,\n identity: verifiedIdentity,\n title: normalizedInput.title,\n description: normalizedInput.description,\n },\n );\n if (branch === undefined) {\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: \"manual\",\n } satisfies DuplicatePrototypeValue;\n }\n\n await commitPath(\n this.#repository,\n repositoryRelativePath(this.#runtime, ref),\n `init: ${ref.slug}`,\n );\n const push = await pushBranch(\n this.#repository,\n this.#runtime.remote,\n branch,\n );\n\n return {\n ref,\n url: getPrototypeUrl(ref),\n remoteStatus: push.remoteStatus,\n } satisfies DuplicatePrototypeValue;\n },\n );\n });\n }\n}\n"]}
@@ -10,6 +10,8 @@ export type RepositorySummaryOptions = {
10
10
  mode: GitMode;
11
11
  remote: string;
12
12
  primaryBranch: string;
13
+ /** True when the running server must restart to load updated dependencies. */
14
+ restartRequired?: boolean;
13
15
  /** Fetch remote-tracking refs before comparing managed update state. */
14
16
  refresh?: boolean;
15
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"repository-summary.d.ts","sourceRoot":"","sources":["../../src/lifecycle/repository-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,OAAO,EAOZ,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,aAAa,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAoHF,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CAuI5B","sourcesContent":["import { relative } from \"node:path\";\nimport {\n getGitManagementCapabilities,\n parseRepositoryRelativePath,\n type BonfireIdentity,\n type GitMode,\n type PrototypeRef,\n type PrototypeSummary,\n type RepositoryAttentionCode,\n type RepositoryChange,\n type RepositoryChangeScope,\n type RepositoryChangeStatus,\n type RepositorySummary,\n} from \"@ebay-dt/bonfire-core\";\nimport type { PrototypeCatalogLike } from \"../prototype-catalog.js\";\nimport {\n type GitRepository,\n type GitStatusFile,\n} from \"../git-repository.js\";\nimport { hasUnresolvedRepositoryOperation } from \"./repository-synchronization.js\";\n\nexport type RepositorySummaryOptions = {\n repository: GitRepository;\n catalog: PrototypeCatalogLike;\n repositoryRoot: string;\n prototypeRoot: string;\n identity: BonfireIdentity;\n mode: GitMode;\n remote: string;\n primaryBranch: string;\n /** Fetch remote-tracking refs before comparing managed update state. */\n refresh?: boolean;\n};\n\ntype SummaryPathContext = {\n scope: RepositoryChangeScope;\n prototype: PrototypeRef | undefined;\n};\n\nfunction normalizePath(value: string) {\n return value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//u, \"\");\n}\n\nfunction pathPrefix(repositoryRoot: string, prototypeRoot: string) {\n const value = normalizePath(relative(repositoryRoot, prototypeRoot));\n return value === \".\" ? \"\" : value.replace(/\\/+$/u, \"\");\n}\n\nfunction summaryKey(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction contextForPath(\n value: string,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n): SummaryPathContext {\n const path = normalizePath(value);\n const rest = prefix === \"\" ? path : path.startsWith(`${prefix}/`) ? path.slice(prefix.length + 1) : null;\n if (rest === null) return { scope: \"out-of-scope\", prototype: undefined };\n\n const segments = rest.split(\"/\");\n const login = segments[0];\n const slug = segments[1];\n if (login === undefined || slug === undefined) {\n return { scope: \"unknown\", prototype: undefined };\n }\n\n const ref = { login, slug } satisfies PrototypeRef;\n const summary = summaries.get(summaryKey(ref));\n if (summary === undefined) return { scope: \"unknown\", prototype: undefined };\n\n return {\n scope: login === identity.login ? \"owned-prototype\" : \"other-prototype\",\n prototype: ref,\n };\n}\n\nfunction safePath(value: string) {\n try {\n return parseRepositoryRelativePath(normalizePath(value));\n } catch {\n return null;\n }\n}\n\nfunction addChange(\n changes: Map<string, RepositoryChange>,\n path: string,\n status: RepositoryChangeStatus,\n context: SummaryPathContext,\n) {\n const safe = safePath(path);\n if (safe === null) return;\n const key = `${status}:${safe}`;\n changes.set(key, {\n path: safe,\n status,\n scope: context.scope,\n ...(context.prototype === undefined ? {} : { prototype: context.prototype }),\n });\n}\n\nfunction statusPaths(file: GitStatusFile) {\n return [file.path, ...(file.from === undefined ? [] : [file.from])];\n}\n\nasync function diffPaths(repository: GitRepository, range: string) {\n const output = await repository.raw([\"diff\", \"--name-only\", \"-z\", range]);\n return output.split(\"\\0\").filter((path) => path.length > 0);\n}\n\nasync function refRelation(repository: GitRepository, left: string, right: string) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new Error(\"Malformed Git ref relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nfunction addDiffChanges(\n changes: Map<string, RepositoryChange>,\n paths: readonly string[],\n status: RepositoryChangeStatus,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n) {\n for (const path of paths) {\n addChange(\n changes,\n path,\n status,\n contextForPath(path, prefix, summaries, identity),\n );\n }\n}\n\nexport async function getRepositorySummary(\n options: RepositorySummaryOptions,\n): Promise<RepositorySummary> {\n const summaries = new Map(\n (await options.catalog.scan()).map((summary) => [\n summaryKey(summary.ref),\n summary,\n ]),\n );\n const prefix = pathPrefix(options.repositoryRoot, options.prototypeRoot);\n const changes = new Map<string, RepositoryChange>();\n const attention = new Set<RepositoryAttentionCode>();\n const status = await options.repository.status();\n const currentBranch = await options.repository.currentBranch();\n const unresolved = await hasUnresolvedRepositoryOperation(options.repository);\n const detached = currentBranch === \"HEAD\" || currentBranch.length === 0;\n const wrongBranch = !detached && currentBranch !== options.identity.login;\n\n for (const file of status.files) {\n const fileStatus =\n file.index.includes(\"U\") || file.workingDirectory.includes(\"U\")\n ? \"unresolved\"\n : \"uncommitted\";\n for (const path of statusPaths(file)) {\n addChange(\n changes,\n path,\n fileStatus,\n contextForPath(path, prefix, summaries, options.identity),\n );\n }\n }\n\n const dirtyWorktree = status.files.length > 0;\n if (unresolved) attention.add(\"unresolved-operation\");\n if (detached) attention.add(\"detached-head\");\n if (wrongBranch) attention.add(\"wrong-branch\");\n\n const remotes = await options.repository.remotes();\n const hasRemote = remotes.some((remote) => remote.name === options.remote);\n let fetchFailed = false;\n if (options.refresh && options.mode === \"managed\" && hasRemote) {\n try {\n await options.repository.fetch(options.remote);\n } catch {\n fetchFailed = true;\n attention.add(\"fetch-failed\");\n }\n }\n const branches = await options.repository.branches();\n const localIdentity = branches.all.includes(options.identity.login);\n const remoteIdentity = `remotes/${options.remote}/${options.identity.login}`;\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemoteIdentity = hasRemote && branches.all.includes(remoteIdentity);\n const hasRemotePrimary = hasRemote && branches.all.includes(remotePrimary);\n let updateCheck: RepositorySummary[\"updateCheck\"] =\n options.mode === \"manual\" ? \"not-checked\" : \"unavailable\";\n\n if (options.mode === \"managed\") {\n if (fetchFailed) {\n updateCheck = \"attention\";\n } else if (!hasRemote) {\n updateCheck = \"unavailable\";\n } else if (!hasRemotePrimary || !localIdentity) {\n updateCheck = \"attention\";\n attention.add(\"missing-primary\");\n } else {\n try {\n const primaryRelation = await refRelation(\n options.repository,\n options.identity.login,\n remotePrimary,\n );\n updateCheck =\n primaryRelation.behind > 0 ? \"updates-available\" : \"up-to-date\";\n if (primaryRelation.behind > 0) {\n if (dirtyWorktree) attention.add(\"dirty-worktree\");\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${options.identity.login}..${remotePrimary}`,\n ),\n \"updates-available\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n updateCheck = \"attention\";\n attention.add(\"unknown\");\n }\n }\n\n if (hasRemoteIdentity && localIdentity) {\n try {\n const identityRelation = await refRelation(\n options.repository,\n options.identity.login,\n remoteIdentity,\n );\n if (identityRelation.ahead > 0) {\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${remoteIdentity}..${options.identity.login}`,\n ),\n \"committed-unpushed\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n attention.add(\"unknown\");\n }\n }\n }\n\n let readiness: RepositorySummary[\"readiness\"] = \"ready\";\n if (detached || wrongBranch || unresolved) {\n readiness = \"blocked\";\n } else if (!status.clean) {\n readiness = \"attention\";\n }\n return {\n mode: options.mode,\n readiness,\n updateCheck,\n changes: [...changes.values()].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n ),\n attention: [...attention].sort(),\n capabilities: getGitManagementCapabilities(options.mode),\n };\n}\n"]}
1
+ {"version":3,"file":"repository-summary.d.ts","sourceRoot":"","sources":["../../src/lifecycle/repository-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,OAAO,EAOZ,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,aAAa,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAoHF,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,iBAAiB,CAAC,CA0I5B","sourcesContent":["import { relative } from \"node:path\";\nimport {\n getGitManagementCapabilities,\n parseRepositoryRelativePath,\n type BonfireIdentity,\n type GitMode,\n type PrototypeRef,\n type PrototypeSummary,\n type RepositoryAttentionCode,\n type RepositoryChange,\n type RepositoryChangeScope,\n type RepositoryChangeStatus,\n type RepositorySummary,\n} from \"@ebay-dt/bonfire-core\";\nimport type { PrototypeCatalogLike } from \"../prototype-catalog.js\";\nimport {\n type GitRepository,\n type GitStatusFile,\n} from \"../git-repository.js\";\nimport { hasUnresolvedRepositoryOperation } from \"./repository-synchronization.js\";\n\nexport type RepositorySummaryOptions = {\n repository: GitRepository;\n catalog: PrototypeCatalogLike;\n repositoryRoot: string;\n prototypeRoot: string;\n identity: BonfireIdentity;\n mode: GitMode;\n remote: string;\n primaryBranch: string;\n /** True when the running server must restart to load updated dependencies. */\n restartRequired?: boolean;\n /** Fetch remote-tracking refs before comparing managed update state. */\n refresh?: boolean;\n};\n\ntype SummaryPathContext = {\n scope: RepositoryChangeScope;\n prototype: PrototypeRef | undefined;\n};\n\nfunction normalizePath(value: string) {\n return value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//u, \"\");\n}\n\nfunction pathPrefix(repositoryRoot: string, prototypeRoot: string) {\n const value = normalizePath(relative(repositoryRoot, prototypeRoot));\n return value === \".\" ? \"\" : value.replace(/\\/+$/u, \"\");\n}\n\nfunction summaryKey(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction contextForPath(\n value: string,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n): SummaryPathContext {\n const path = normalizePath(value);\n const rest = prefix === \"\" ? path : path.startsWith(`${prefix}/`) ? path.slice(prefix.length + 1) : null;\n if (rest === null) return { scope: \"out-of-scope\", prototype: undefined };\n\n const segments = rest.split(\"/\");\n const login = segments[0];\n const slug = segments[1];\n if (login === undefined || slug === undefined) {\n return { scope: \"unknown\", prototype: undefined };\n }\n\n const ref = { login, slug } satisfies PrototypeRef;\n const summary = summaries.get(summaryKey(ref));\n if (summary === undefined) return { scope: \"unknown\", prototype: undefined };\n\n return {\n scope: login === identity.login ? \"owned-prototype\" : \"other-prototype\",\n prototype: ref,\n };\n}\n\nfunction safePath(value: string) {\n try {\n return parseRepositoryRelativePath(normalizePath(value));\n } catch {\n return null;\n }\n}\n\nfunction addChange(\n changes: Map<string, RepositoryChange>,\n path: string,\n status: RepositoryChangeStatus,\n context: SummaryPathContext,\n) {\n const safe = safePath(path);\n if (safe === null) return;\n const key = `${status}:${safe}`;\n changes.set(key, {\n path: safe,\n status,\n scope: context.scope,\n ...(context.prototype === undefined ? {} : { prototype: context.prototype }),\n });\n}\n\nfunction statusPaths(file: GitStatusFile) {\n return [file.path, ...(file.from === undefined ? [] : [file.from])];\n}\n\nasync function diffPaths(repository: GitRepository, range: string) {\n const output = await repository.raw([\"diff\", \"--name-only\", \"-z\", range]);\n return output.split(\"\\0\").filter((path) => path.length > 0);\n}\n\nasync function refRelation(repository: GitRepository, left: string, right: string) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new Error(\"Malformed Git ref relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nfunction addDiffChanges(\n changes: Map<string, RepositoryChange>,\n paths: readonly string[],\n status: RepositoryChangeStatus,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n) {\n for (const path of paths) {\n addChange(\n changes,\n path,\n status,\n contextForPath(path, prefix, summaries, identity),\n );\n }\n}\n\nexport async function getRepositorySummary(\n options: RepositorySummaryOptions,\n): Promise<RepositorySummary> {\n const summaries = new Map(\n (await options.catalog.scan()).map((summary) => [\n summaryKey(summary.ref),\n summary,\n ]),\n );\n const prefix = pathPrefix(options.repositoryRoot, options.prototypeRoot);\n const changes = new Map<string, RepositoryChange>();\n const attention = new Set<RepositoryAttentionCode>();\n const status = await options.repository.status();\n const currentBranch = await options.repository.currentBranch();\n const unresolved = await hasUnresolvedRepositoryOperation(options.repository);\n const detached = currentBranch === \"HEAD\" || currentBranch.length === 0;\n const wrongBranch = !detached && currentBranch !== options.identity.login;\n\n for (const file of status.files) {\n const fileStatus =\n file.index.includes(\"U\") || file.workingDirectory.includes(\"U\")\n ? \"unresolved\"\n : \"uncommitted\";\n for (const path of statusPaths(file)) {\n addChange(\n changes,\n path,\n fileStatus,\n contextForPath(path, prefix, summaries, options.identity),\n );\n }\n }\n\n const dirtyWorktree = status.files.length > 0;\n if (unresolved) attention.add(\"unresolved-operation\");\n if (detached) attention.add(\"detached-head\");\n if (wrongBranch) attention.add(\"wrong-branch\");\n\n const remotes = await options.repository.remotes();\n const hasRemote = remotes.some((remote) => remote.name === options.remote);\n let fetchFailed = false;\n if (options.refresh && options.mode === \"managed\" && hasRemote) {\n try {\n await options.repository.fetch(options.remote);\n } catch {\n fetchFailed = true;\n attention.add(\"fetch-failed\");\n }\n }\n const branches = await options.repository.branches();\n const localIdentity = branches.all.includes(options.identity.login);\n const remoteIdentity = `remotes/${options.remote}/${options.identity.login}`;\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemoteIdentity = hasRemote && branches.all.includes(remoteIdentity);\n const hasRemotePrimary = hasRemote && branches.all.includes(remotePrimary);\n let updateCheck: RepositorySummary[\"updateCheck\"] =\n options.mode === \"manual\" ? \"not-checked\" : \"unavailable\";\n\n if (options.mode === \"managed\") {\n if (fetchFailed) {\n updateCheck = \"attention\";\n } else if (!hasRemote) {\n updateCheck = \"unavailable\";\n } else if (!hasRemotePrimary || !localIdentity) {\n updateCheck = \"attention\";\n attention.add(\"missing-primary\");\n } else {\n try {\n const primaryRelation = await refRelation(\n options.repository,\n options.identity.login,\n remotePrimary,\n );\n updateCheck =\n primaryRelation.behind > 0 ? \"updates-available\" : \"up-to-date\";\n if (primaryRelation.behind > 0) {\n if (dirtyWorktree) attention.add(\"dirty-worktree\");\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${options.identity.login}..${remotePrimary}`,\n ),\n \"updates-available\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n updateCheck = \"attention\";\n attention.add(\"unknown\");\n }\n }\n\n if (hasRemoteIdentity && localIdentity) {\n try {\n const identityRelation = await refRelation(\n options.repository,\n options.identity.login,\n remoteIdentity,\n );\n if (identityRelation.ahead > 0) {\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${remoteIdentity}..${options.identity.login}`,\n ),\n \"committed-unpushed\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n attention.add(\"unknown\");\n }\n }\n }\n\n let readiness: RepositorySummary[\"readiness\"] = \"ready\";\n if (detached || wrongBranch || unresolved) {\n readiness = \"blocked\";\n } else if (!status.clean) {\n readiness = \"attention\";\n }\n return {\n mode: options.mode,\n ...(options.restartRequired === undefined\n ? {}\n : { restartRequired: options.restartRequired }),\n readiness,\n updateCheck,\n changes: [...changes.values()].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n ),\n attention: [...attention].sort(),\n capabilities: getGitManagementCapabilities(options.mode),\n };\n}\n"]}
@@ -172,6 +172,9 @@ export async function getRepositorySummary(options) {
172
172
  }
173
173
  return {
174
174
  mode: options.mode,
175
+ ...(options.restartRequired === undefined
176
+ ? {}
177
+ : { restartRequired: options.restartRequired }),
175
178
  readiness,
176
179
  updateCheck,
177
180
  changes: [...changes.values()].sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0),
@@ -1 +1 @@
1
- {"version":3,"file":"repository-summary.js","sourceRoot":"","sources":["../../src/lifecycle/repository-summary.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative } from \"node:path\";\nimport {\n getGitManagementCapabilities,\n parseRepositoryRelativePath,\n type BonfireIdentity,\n type GitMode,\n type PrototypeRef,\n type PrototypeSummary,\n type RepositoryAttentionCode,\n type RepositoryChange,\n type RepositoryChangeScope,\n type RepositoryChangeStatus,\n type RepositorySummary,\n} from \"@ebay-dt/bonfire-core\";\nimport type { PrototypeCatalogLike } from \"../prototype-catalog.js\";\nimport {\n type GitRepository,\n type GitStatusFile,\n} from \"../git-repository.js\";\nimport { hasUnresolvedRepositoryOperation } from \"./repository-synchronization.js\";\n\nexport type RepositorySummaryOptions = {\n repository: GitRepository;\n catalog: PrototypeCatalogLike;\n repositoryRoot: string;\n prototypeRoot: string;\n identity: BonfireIdentity;\n mode: GitMode;\n remote: string;\n primaryBranch: string;\n /** Fetch remote-tracking refs before comparing managed update state. */\n refresh?: boolean;\n};\n\ntype SummaryPathContext = {\n scope: RepositoryChangeScope;\n prototype: PrototypeRef | undefined;\n};\n\nfunction normalizePath(value: string) {\n return value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//u, \"\");\n}\n\nfunction pathPrefix(repositoryRoot: string, prototypeRoot: string) {\n const value = normalizePath(relative(repositoryRoot, prototypeRoot));\n return value === \".\" ? \"\" : value.replace(/\\/+$/u, \"\");\n}\n\nfunction summaryKey(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction contextForPath(\n value: string,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n): SummaryPathContext {\n const path = normalizePath(value);\n const rest = prefix === \"\" ? path : path.startsWith(`${prefix}/`) ? path.slice(prefix.length + 1) : null;\n if (rest === null) return { scope: \"out-of-scope\", prototype: undefined };\n\n const segments = rest.split(\"/\");\n const login = segments[0];\n const slug = segments[1];\n if (login === undefined || slug === undefined) {\n return { scope: \"unknown\", prototype: undefined };\n }\n\n const ref = { login, slug } satisfies PrototypeRef;\n const summary = summaries.get(summaryKey(ref));\n if (summary === undefined) return { scope: \"unknown\", prototype: undefined };\n\n return {\n scope: login === identity.login ? \"owned-prototype\" : \"other-prototype\",\n prototype: ref,\n };\n}\n\nfunction safePath(value: string) {\n try {\n return parseRepositoryRelativePath(normalizePath(value));\n } catch {\n return null;\n }\n}\n\nfunction addChange(\n changes: Map<string, RepositoryChange>,\n path: string,\n status: RepositoryChangeStatus,\n context: SummaryPathContext,\n) {\n const safe = safePath(path);\n if (safe === null) return;\n const key = `${status}:${safe}`;\n changes.set(key, {\n path: safe,\n status,\n scope: context.scope,\n ...(context.prototype === undefined ? {} : { prototype: context.prototype }),\n });\n}\n\nfunction statusPaths(file: GitStatusFile) {\n return [file.path, ...(file.from === undefined ? [] : [file.from])];\n}\n\nasync function diffPaths(repository: GitRepository, range: string) {\n const output = await repository.raw([\"diff\", \"--name-only\", \"-z\", range]);\n return output.split(\"\\0\").filter((path) => path.length > 0);\n}\n\nasync function refRelation(repository: GitRepository, left: string, right: string) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new Error(\"Malformed Git ref relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nfunction addDiffChanges(\n changes: Map<string, RepositoryChange>,\n paths: readonly string[],\n status: RepositoryChangeStatus,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n) {\n for (const path of paths) {\n addChange(\n changes,\n path,\n status,\n contextForPath(path, prefix, summaries, identity),\n );\n }\n}\n\nexport async function getRepositorySummary(\n options: RepositorySummaryOptions,\n): Promise<RepositorySummary> {\n const summaries = new Map(\n (await options.catalog.scan()).map((summary) => [\n summaryKey(summary.ref),\n summary,\n ]),\n );\n const prefix = pathPrefix(options.repositoryRoot, options.prototypeRoot);\n const changes = new Map<string, RepositoryChange>();\n const attention = new Set<RepositoryAttentionCode>();\n const status = await options.repository.status();\n const currentBranch = await options.repository.currentBranch();\n const unresolved = await hasUnresolvedRepositoryOperation(options.repository);\n const detached = currentBranch === \"HEAD\" || currentBranch.length === 0;\n const wrongBranch = !detached && currentBranch !== options.identity.login;\n\n for (const file of status.files) {\n const fileStatus =\n file.index.includes(\"U\") || file.workingDirectory.includes(\"U\")\n ? \"unresolved\"\n : \"uncommitted\";\n for (const path of statusPaths(file)) {\n addChange(\n changes,\n path,\n fileStatus,\n contextForPath(path, prefix, summaries, options.identity),\n );\n }\n }\n\n const dirtyWorktree = status.files.length > 0;\n if (unresolved) attention.add(\"unresolved-operation\");\n if (detached) attention.add(\"detached-head\");\n if (wrongBranch) attention.add(\"wrong-branch\");\n\n const remotes = await options.repository.remotes();\n const hasRemote = remotes.some((remote) => remote.name === options.remote);\n let fetchFailed = false;\n if (options.refresh && options.mode === \"managed\" && hasRemote) {\n try {\n await options.repository.fetch(options.remote);\n } catch {\n fetchFailed = true;\n attention.add(\"fetch-failed\");\n }\n }\n const branches = await options.repository.branches();\n const localIdentity = branches.all.includes(options.identity.login);\n const remoteIdentity = `remotes/${options.remote}/${options.identity.login}`;\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemoteIdentity = hasRemote && branches.all.includes(remoteIdentity);\n const hasRemotePrimary = hasRemote && branches.all.includes(remotePrimary);\n let updateCheck: RepositorySummary[\"updateCheck\"] =\n options.mode === \"manual\" ? \"not-checked\" : \"unavailable\";\n\n if (options.mode === \"managed\") {\n if (fetchFailed) {\n updateCheck = \"attention\";\n } else if (!hasRemote) {\n updateCheck = \"unavailable\";\n } else if (!hasRemotePrimary || !localIdentity) {\n updateCheck = \"attention\";\n attention.add(\"missing-primary\");\n } else {\n try {\n const primaryRelation = await refRelation(\n options.repository,\n options.identity.login,\n remotePrimary,\n );\n updateCheck =\n primaryRelation.behind > 0 ? \"updates-available\" : \"up-to-date\";\n if (primaryRelation.behind > 0) {\n if (dirtyWorktree) attention.add(\"dirty-worktree\");\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${options.identity.login}..${remotePrimary}`,\n ),\n \"updates-available\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n updateCheck = \"attention\";\n attention.add(\"unknown\");\n }\n }\n\n if (hasRemoteIdentity && localIdentity) {\n try {\n const identityRelation = await refRelation(\n options.repository,\n options.identity.login,\n remoteIdentity,\n );\n if (identityRelation.ahead > 0) {\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${remoteIdentity}..${options.identity.login}`,\n ),\n \"committed-unpushed\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n attention.add(\"unknown\");\n }\n }\n }\n\n let readiness: RepositorySummary[\"readiness\"] = \"ready\";\n if (detached || wrongBranch || unresolved) {\n readiness = \"blocked\";\n } else if (!status.clean) {\n readiness = \"attention\";\n }\n return {\n mode: options.mode,\n readiness,\n updateCheck,\n changes: [...changes.values()].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n ),\n attention: [...attention].sort(),\n capabilities: getGitManagementCapabilities(options.mode),\n };\n}\n"]}
1
+ {"version":3,"file":"repository-summary.js","sourceRoot":"","sources":["../../src/lifecycle/repository-summary.ts"],"names":[],"mappings":"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","sourcesContent":["import { relative } from \"node:path\";\nimport {\n getGitManagementCapabilities,\n parseRepositoryRelativePath,\n type BonfireIdentity,\n type GitMode,\n type PrototypeRef,\n type PrototypeSummary,\n type RepositoryAttentionCode,\n type RepositoryChange,\n type RepositoryChangeScope,\n type RepositoryChangeStatus,\n type RepositorySummary,\n} from \"@ebay-dt/bonfire-core\";\nimport type { PrototypeCatalogLike } from \"../prototype-catalog.js\";\nimport {\n type GitRepository,\n type GitStatusFile,\n} from \"../git-repository.js\";\nimport { hasUnresolvedRepositoryOperation } from \"./repository-synchronization.js\";\n\nexport type RepositorySummaryOptions = {\n repository: GitRepository;\n catalog: PrototypeCatalogLike;\n repositoryRoot: string;\n prototypeRoot: string;\n identity: BonfireIdentity;\n mode: GitMode;\n remote: string;\n primaryBranch: string;\n /** True when the running server must restart to load updated dependencies. */\n restartRequired?: boolean;\n /** Fetch remote-tracking refs before comparing managed update state. */\n refresh?: boolean;\n};\n\ntype SummaryPathContext = {\n scope: RepositoryChangeScope;\n prototype: PrototypeRef | undefined;\n};\n\nfunction normalizePath(value: string) {\n return value.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//u, \"\");\n}\n\nfunction pathPrefix(repositoryRoot: string, prototypeRoot: string) {\n const value = normalizePath(relative(repositoryRoot, prototypeRoot));\n return value === \".\" ? \"\" : value.replace(/\\/+$/u, \"\");\n}\n\nfunction summaryKey(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction contextForPath(\n value: string,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n): SummaryPathContext {\n const path = normalizePath(value);\n const rest = prefix === \"\" ? path : path.startsWith(`${prefix}/`) ? path.slice(prefix.length + 1) : null;\n if (rest === null) return { scope: \"out-of-scope\", prototype: undefined };\n\n const segments = rest.split(\"/\");\n const login = segments[0];\n const slug = segments[1];\n if (login === undefined || slug === undefined) {\n return { scope: \"unknown\", prototype: undefined };\n }\n\n const ref = { login, slug } satisfies PrototypeRef;\n const summary = summaries.get(summaryKey(ref));\n if (summary === undefined) return { scope: \"unknown\", prototype: undefined };\n\n return {\n scope: login === identity.login ? \"owned-prototype\" : \"other-prototype\",\n prototype: ref,\n };\n}\n\nfunction safePath(value: string) {\n try {\n return parseRepositoryRelativePath(normalizePath(value));\n } catch {\n return null;\n }\n}\n\nfunction addChange(\n changes: Map<string, RepositoryChange>,\n path: string,\n status: RepositoryChangeStatus,\n context: SummaryPathContext,\n) {\n const safe = safePath(path);\n if (safe === null) return;\n const key = `${status}:${safe}`;\n changes.set(key, {\n path: safe,\n status,\n scope: context.scope,\n ...(context.prototype === undefined ? {} : { prototype: context.prototype }),\n });\n}\n\nfunction statusPaths(file: GitStatusFile) {\n return [file.path, ...(file.from === undefined ? [] : [file.from])];\n}\n\nasync function diffPaths(repository: GitRepository, range: string) {\n const output = await repository.raw([\"diff\", \"--name-only\", \"-z\", range]);\n return output.split(\"\\0\").filter((path) => path.length > 0);\n}\n\nasync function refRelation(repository: GitRepository, left: string, right: string) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new Error(\"Malformed Git ref relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nfunction addDiffChanges(\n changes: Map<string, RepositoryChange>,\n paths: readonly string[],\n status: RepositoryChangeStatus,\n prefix: string,\n summaries: ReadonlyMap<string, PrototypeSummary>,\n identity: BonfireIdentity,\n) {\n for (const path of paths) {\n addChange(\n changes,\n path,\n status,\n contextForPath(path, prefix, summaries, identity),\n );\n }\n}\n\nexport async function getRepositorySummary(\n options: RepositorySummaryOptions,\n): Promise<RepositorySummary> {\n const summaries = new Map(\n (await options.catalog.scan()).map((summary) => [\n summaryKey(summary.ref),\n summary,\n ]),\n );\n const prefix = pathPrefix(options.repositoryRoot, options.prototypeRoot);\n const changes = new Map<string, RepositoryChange>();\n const attention = new Set<RepositoryAttentionCode>();\n const status = await options.repository.status();\n const currentBranch = await options.repository.currentBranch();\n const unresolved = await hasUnresolvedRepositoryOperation(options.repository);\n const detached = currentBranch === \"HEAD\" || currentBranch.length === 0;\n const wrongBranch = !detached && currentBranch !== options.identity.login;\n\n for (const file of status.files) {\n const fileStatus =\n file.index.includes(\"U\") || file.workingDirectory.includes(\"U\")\n ? \"unresolved\"\n : \"uncommitted\";\n for (const path of statusPaths(file)) {\n addChange(\n changes,\n path,\n fileStatus,\n contextForPath(path, prefix, summaries, options.identity),\n );\n }\n }\n\n const dirtyWorktree = status.files.length > 0;\n if (unresolved) attention.add(\"unresolved-operation\");\n if (detached) attention.add(\"detached-head\");\n if (wrongBranch) attention.add(\"wrong-branch\");\n\n const remotes = await options.repository.remotes();\n const hasRemote = remotes.some((remote) => remote.name === options.remote);\n let fetchFailed = false;\n if (options.refresh && options.mode === \"managed\" && hasRemote) {\n try {\n await options.repository.fetch(options.remote);\n } catch {\n fetchFailed = true;\n attention.add(\"fetch-failed\");\n }\n }\n const branches = await options.repository.branches();\n const localIdentity = branches.all.includes(options.identity.login);\n const remoteIdentity = `remotes/${options.remote}/${options.identity.login}`;\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemoteIdentity = hasRemote && branches.all.includes(remoteIdentity);\n const hasRemotePrimary = hasRemote && branches.all.includes(remotePrimary);\n let updateCheck: RepositorySummary[\"updateCheck\"] =\n options.mode === \"manual\" ? \"not-checked\" : \"unavailable\";\n\n if (options.mode === \"managed\") {\n if (fetchFailed) {\n updateCheck = \"attention\";\n } else if (!hasRemote) {\n updateCheck = \"unavailable\";\n } else if (!hasRemotePrimary || !localIdentity) {\n updateCheck = \"attention\";\n attention.add(\"missing-primary\");\n } else {\n try {\n const primaryRelation = await refRelation(\n options.repository,\n options.identity.login,\n remotePrimary,\n );\n updateCheck =\n primaryRelation.behind > 0 ? \"updates-available\" : \"up-to-date\";\n if (primaryRelation.behind > 0) {\n if (dirtyWorktree) attention.add(\"dirty-worktree\");\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${options.identity.login}..${remotePrimary}`,\n ),\n \"updates-available\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n updateCheck = \"attention\";\n attention.add(\"unknown\");\n }\n }\n\n if (hasRemoteIdentity && localIdentity) {\n try {\n const identityRelation = await refRelation(\n options.repository,\n options.identity.login,\n remoteIdentity,\n );\n if (identityRelation.ahead > 0) {\n addDiffChanges(\n changes,\n await diffPaths(\n options.repository,\n `${remoteIdentity}..${options.identity.login}`,\n ),\n \"committed-unpushed\",\n prefix,\n summaries,\n options.identity,\n );\n }\n } catch {\n attention.add(\"unknown\");\n }\n }\n }\n\n let readiness: RepositorySummary[\"readiness\"] = \"ready\";\n if (detached || wrongBranch || unresolved) {\n readiness = \"blocked\";\n } else if (!status.clean) {\n readiness = \"attention\";\n }\n return {\n mode: options.mode,\n ...(options.restartRequired === undefined\n ? {}\n : { restartRequired: options.restartRequired }),\n readiness,\n updateCheck,\n changes: [...changes.values()].sort((left, right) =>\n left.path < right.path ? -1 : left.path > right.path ? 1 : 0,\n ),\n attention: [...attention].sort(),\n capabilities: getGitManagementCapabilities(options.mode),\n };\n}\n"]}
@@ -20,6 +20,7 @@ export type SynchronizeIdentityBranchOptions = {
20
20
  identityBranch: string;
21
21
  primaryBranch: string;
22
22
  remote: string;
23
+ managedPaths?: readonly string[];
23
24
  };
24
25
  export declare function hasUnresolvedRepositoryOperation(repository: GitRepository): Promise<boolean>;
25
26
  export declare function assertIdentityBranchReady(repository: GitRepository, identityBranch: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"repository-synchronization.d.ts","sourceRoot":"","sources":["../../src/lifecycle/repository-synchronization.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,6BAA6B,GACrC,gBAAgB,GAChB,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,MAAM,2BAA2B,GACnC,eAAe,GACf,sBAAsB,GACtB,iBAAiB,GACjB,qBAAqB,GACrB,cAAc,GACd,cAAc,GACd,aAAa,CAAC;AAElB,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GACvC,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB,CAAC,GACF,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,6BAA6B,CAAC;CACvC,CAAC,GACF,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,2BAA2B,CAAC;CACrC,CAAC,CAAC;AAEP,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAgDF,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,aAAa,oBAO1B;AAkFD,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,aAAa,EACzB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,aAAa,EACzB,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,+BAA+B,CAAC,CAgL1C","sourcesContent":["import { lstat } from \"node:fs/promises\";\nimport { isAbsolute, resolve } from \"node:path\";\nimport {\n GitRepositoryError,\n type GitRepository,\n} from \"../git-repository.js\";\n\nexport type SynchronizationDeferredReason =\n | \"dirty-worktree\"\n | \"fetch-failed\"\n | \"merge-conflict\";\n\nexport type SynchronizationUnsafeReason =\n | \"detached-head\"\n | \"unresolved-operation\"\n | \"missing-primary\"\n | \"identity-divergence\"\n | \"failed-abort\"\n | \"merge-failed\"\n | \"push-failed\";\n\ntype SynchronizationBase = {\n branch: string | null;\n changed: boolean;\n pushed: boolean;\n affectedPaths: readonly string[];\n};\n\nexport type RepositorySynchronizationResult =\n | (SynchronizationBase & {\n status: \"synchronized\";\n })\n | (SynchronizationBase & {\n status: \"deferred\";\n reason: SynchronizationDeferredReason;\n })\n | (SynchronizationBase & {\n status: \"unsafe\";\n reason: SynchronizationUnsafeReason;\n });\n\nexport type SynchronizeIdentityBranchOptions = {\n identityBranch: string;\n primaryBranch: string;\n remote: string;\n};\n\nconst OPERATION_MARKERS = [\n \"MERGE_HEAD\",\n \"CHERRY_PICK_HEAD\",\n \"REVERT_HEAD\",\n \"rebase-merge\",\n \"rebase-apply\",\n] as const;\n\nfunction assertBranch(value: string, option: string) {\n if (\n value.length === 0 ||\n value.startsWith(\"-\") ||\n value.includes(\"\\0\") ||\n /\\s/u.test(value) ||\n value.includes(\"@{\") ||\n value.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction remoteRef(remote: string, branch: string) {\n return `remotes/${remote}/${branch}`;\n}\n\nfunction branchRef(branch: string) {\n return `refs/heads/${branch}`;\n}\n\nasync function markerExists(repository: GitRepository, marker: string) {\n const markerPath = (await repository.raw([\"rev-parse\", \"--git-path\", marker])).trim();\n if (markerPath.length === 0) return false;\n const absolutePath = isAbsolute(markerPath)\n ? markerPath\n : resolve(repository.repositoryRoot, markerPath);\n try {\n await lstat(absolutePath);\n return true;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nexport async function hasUnresolvedRepositoryOperation(\n repository: GitRepository,\n) {\n for (const marker of OPERATION_MARKERS) {\n if (await markerExists(repository, marker)) return true;\n }\n const status = await repository.status();\n return hasUnmergedFiles(status.files);\n}\n\nfunction hasUnmergedFiles(files: readonly { index: string; workingDirectory: string }[]) {\n return files.some(\n (file) => file.index.includes(\"U\") || file.workingDirectory.includes(\"U\"),\n );\n}\n\nasync function refCommit(repository: GitRepository, ref: string) {\n const value = await repository.raw([\"rev-parse\", \"--verify\", `${ref}^{commit}`]);\n const commit = value.trim();\n if (!/^[0-9a-f]{40}$/iu.test(commit)) {\n throw new GitRepositoryError(\"malformed-output\", \"ref-commit\");\n }\n return commit;\n}\n\nasync function compareRefs(\n repository: GitRepository,\n left: string,\n right: string,\n) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"ref-relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nasync function safelyAdvanceLocalPrimary(\n repository: GitRepository,\n primaryBranch: string,\n primaryRemoteRef: string,\n localPrimaryCommit: string,\n) {\n await repository.raw([\n \"update-ref\",\n branchRef(primaryBranch),\n primaryRemoteRef,\n localPrimaryCommit,\n ]);\n}\n\nfunction deferred(\n branch: string | null,\n reason: SynchronizationDeferredReason,\n affectedPaths: readonly string[] = [],\n): RepositorySynchronizationResult {\n return {\n status: \"deferred\",\n branch,\n changed: false,\n pushed: false,\n affectedPaths,\n reason,\n };\n}\n\nfunction unsafe(\n branch: string | null,\n reason: SynchronizationUnsafeReason,\n options: Partial<SynchronizationBase> = {},\n): RepositorySynchronizationResult {\n return {\n status: \"unsafe\",\n branch,\n changed: options.changed ?? false,\n pushed: options.pushed ?? false,\n affectedPaths: options.affectedPaths ?? [],\n reason,\n };\n}\n\nexport async function assertIdentityBranchReady(\n repository: GitRepository,\n identityBranch: string,\n): Promise<void> {\n assertBranch(identityBranch, \"identity-branch\");\n const currentBranch = await repository.currentBranch();\n if (currentBranch === \"HEAD\" || currentBranch.length === 0) {\n throw new GitRepositoryError(\"conflict\", \"current-branch\");\n }\n if (currentBranch !== identityBranch) {\n throw new GitRepositoryError(\"conflict\", \"identity-branch\");\n }\n if (await hasUnresolvedRepositoryOperation(repository)) {\n throw new GitRepositoryError(\"conflict\", \"unresolved-operation\");\n }\n const status = await repository.status();\n if (hasUnmergedFiles(status.files)) {\n throw new GitRepositoryError(\"conflict\", \"unresolved-operation\");\n }\n}\n\n/**\n * Synchronize an identity branch from primary without checking out local\n * primary. Remote-tracking refs are the source of truth whenever a configured\n * remote is available. The result distinguishes non-blocking attention from\n * unsafe repository state so callers can keep authentication/read-only flows\n * available.\n */\nexport async function synchronizeIdentityBranch(\n repository: GitRepository,\n options: SynchronizeIdentityBranchOptions,\n): Promise<RepositorySynchronizationResult> {\n assertBranch(options.identityBranch, \"identity-branch\");\n assertBranch(options.primaryBranch, \"primary-branch\");\n assertBranch(options.remote, \"remote\");\n\n if (options.identityBranch === options.primaryBranch) {\n throw new GitRepositoryError(\"invalid-configuration\", \"identity-primary-branch\");\n }\n\n const currentBranch = await repository.currentBranch();\n if (currentBranch === \"HEAD\" || currentBranch.length === 0) {\n return unsafe(null, \"detached-head\");\n }\n\n if (await hasUnresolvedRepositoryOperation(repository)) {\n return unsafe(currentBranch, \"unresolved-operation\");\n }\n\n const status = await repository.status();\n if (hasUnmergedFiles(status.files)) {\n return unsafe(currentBranch, \"unresolved-operation\", {\n affectedPaths: status.files.map((file) => file.path),\n });\n }\n if (!status.clean) {\n return deferred(\n currentBranch,\n \"dirty-worktree\",\n status.files.map((file) => file.path),\n );\n }\n\n const configuredRemote = (await repository.remotes()).some(\n (remote) => remote.name === options.remote,\n );\n if (configuredRemote) {\n try {\n await repository.fetch(options.remote);\n } catch (error) {\n if (\n error instanceof GitRepositoryError &&\n error.kind === \"invalid-configuration\"\n ) {\n throw error;\n }\n return deferred(currentBranch, \"fetch-failed\");\n }\n }\n\n const branches = await repository.branches();\n const localPrimary = branches.all.includes(options.primaryBranch);\n const primaryRemote = remoteRef(options.remote, options.primaryBranch);\n const remotePrimary = configuredRemote && branches.all.includes(primaryRemote);\n if (configuredRemote ? !remotePrimary : !localPrimary) {\n return unsafe(currentBranch, \"missing-primary\");\n }\n\n const localIdentity = branches.all.includes(options.identityBranch);\n const identityRemote = remoteRef(options.remote, options.identityBranch);\n const remoteIdentity =\n configuredRemote && branches.all.includes(identityRemote);\n\n if (localIdentity && remoteIdentity) {\n const relation = await compareRefs(\n repository,\n options.identityBranch,\n identityRemote,\n );\n if (relation.ahead > 0 && relation.behind > 0) {\n return unsafe(currentBranch, \"identity-divergence\");\n }\n }\n\n let primaryAdvance:\n | { localCommit: string; remoteRef: string }\n | undefined;\n if (localPrimary && remotePrimary) {\n const relation = await compareRefs(\n repository,\n options.primaryBranch,\n primaryRemote,\n );\n if (relation.ahead === 0 && relation.behind > 0) {\n primaryAdvance = {\n localCommit: await refCommit(repository, options.primaryBranch),\n remoteRef: primaryRemote,\n };\n }\n }\n\n const sourceRef = remotePrimary ? primaryRemote : options.primaryBranch;\n if (!localIdentity) {\n if (remoteIdentity) {\n await repository.checkout([\n \"-b\",\n options.identityBranch,\n \"--track\",\n `${options.remote}/${options.identityBranch}`,\n ]);\n } else {\n await repository.checkout([\"-b\", options.identityBranch, sourceRef]);\n }\n } else if (currentBranch !== options.identityBranch) {\n await repository.checkout([options.identityBranch]);\n }\n\n if (primaryAdvance && currentBranch !== options.primaryBranch) {\n await safelyAdvanceLocalPrimary(\n repository,\n options.primaryBranch,\n primaryAdvance.remoteRef,\n primaryAdvance.localCommit,\n );\n }\n\n if (localIdentity && remoteIdentity) {\n const relation = await compareRefs(\n repository,\n options.identityBranch,\n identityRemote,\n );\n if (relation.ahead === 0 && relation.behind > 0) {\n await repository.merge([identityRemote, \"--ff-only\"]);\n }\n }\n\n const beforeMerge = await refCommit(repository, options.identityBranch);\n try {\n await repository.merge([sourceRef, \"--no-edit\"]);\n } catch (error) {\n if (!(error instanceof GitRepositoryError) || error.kind !== \"conflict\") {\n return unsafe(options.identityBranch, \"merge-failed\");\n }\n let affectedPaths: readonly string[] = [];\n try {\n affectedPaths = (await repository.status()).files.map((file) => file.path);\n } catch {\n // Preserve the conflict classification even if status cannot be read.\n }\n try {\n await repository.raw([\"merge\", \"--abort\"]);\n } catch {\n return unsafe(options.identityBranch, \"failed-abort\", {\n affectedPaths,\n });\n }\n return deferred(options.identityBranch, \"merge-conflict\", affectedPaths);\n }\n\n const afterMerge = await refCommit(repository, options.identityBranch);\n const changed = beforeMerge !== afterMerge;\n if (!changed || !configuredRemote) {\n return {\n status: \"synchronized\",\n branch: options.identityBranch,\n changed,\n pushed: false,\n affectedPaths: [],\n };\n }\n\n try {\n await repository.push(options.remote, options.identityBranch, [\n \"--set-upstream\",\n ]);\n } catch {\n return unsafe(options.identityBranch, \"push-failed\", { changed });\n }\n\n return {\n status: \"synchronized\",\n branch: options.identityBranch,\n changed: true,\n pushed: true,\n affectedPaths: [],\n };\n}\n"]}
1
+ {"version":3,"file":"repository-synchronization.d.ts","sourceRoot":"","sources":["../../src/lifecycle/repository-synchronization.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,6BAA6B,GACrC,gBAAgB,GAChB,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,MAAM,2BAA2B,GACnC,eAAe,GACf,sBAAsB,GACtB,iBAAiB,GACjB,qBAAqB,GACrB,cAAc,GACd,cAAc,GACd,aAAa,CAAC;AAElB,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GACvC,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB,CAAC,GACF,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,6BAA6B,CAAC;CACvC,CAAC,GACF,CAAC,mBAAmB,GAAG;IACrB,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,2BAA2B,CAAC;CACrC,CAAC,CAAC;AAEP,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC,CAAC;AAgDF,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,aAAa,oBAO1B;AAkFD,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,aAAa,EACzB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,aAAa,EACzB,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,+BAA+B,CAAC,CAkN1C","sourcesContent":["import { lstat } from \"node:fs/promises\";\nimport { isAbsolute, resolve } from \"node:path\";\nimport {\n GitRepositoryError,\n restorePathFromRef,\n type GitRepository,\n} from \"../git-repository.js\";\n\nexport type SynchronizationDeferredReason =\n | \"dirty-worktree\"\n | \"fetch-failed\"\n | \"merge-conflict\";\n\nexport type SynchronizationUnsafeReason =\n | \"detached-head\"\n | \"unresolved-operation\"\n | \"missing-primary\"\n | \"identity-divergence\"\n | \"failed-abort\"\n | \"merge-failed\"\n | \"push-failed\";\n\ntype SynchronizationBase = {\n branch: string | null;\n changed: boolean;\n pushed: boolean;\n affectedPaths: readonly string[];\n};\n\nexport type RepositorySynchronizationResult =\n | (SynchronizationBase & {\n status: \"synchronized\";\n })\n | (SynchronizationBase & {\n status: \"deferred\";\n reason: SynchronizationDeferredReason;\n })\n | (SynchronizationBase & {\n status: \"unsafe\";\n reason: SynchronizationUnsafeReason;\n });\n\nexport type SynchronizeIdentityBranchOptions = {\n identityBranch: string;\n primaryBranch: string;\n remote: string;\n managedPaths?: readonly string[];\n};\n\nconst OPERATION_MARKERS = [\n \"MERGE_HEAD\",\n \"CHERRY_PICK_HEAD\",\n \"REVERT_HEAD\",\n \"rebase-merge\",\n \"rebase-apply\",\n] as const;\n\nfunction assertBranch(value: string, option: string) {\n if (\n value.length === 0 ||\n value.startsWith(\"-\") ||\n value.includes(\"\\0\") ||\n /\\s/u.test(value) ||\n value.includes(\"@{\") ||\n value.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction remoteRef(remote: string, branch: string) {\n return `remotes/${remote}/${branch}`;\n}\n\nfunction branchRef(branch: string) {\n return `refs/heads/${branch}`;\n}\n\nasync function markerExists(repository: GitRepository, marker: string) {\n const markerPath = (await repository.raw([\"rev-parse\", \"--git-path\", marker])).trim();\n if (markerPath.length === 0) return false;\n const absolutePath = isAbsolute(markerPath)\n ? markerPath\n : resolve(repository.repositoryRoot, markerPath);\n try {\n await lstat(absolutePath);\n return true;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nexport async function hasUnresolvedRepositoryOperation(\n repository: GitRepository,\n) {\n for (const marker of OPERATION_MARKERS) {\n if (await markerExists(repository, marker)) return true;\n }\n const status = await repository.status();\n return hasUnmergedFiles(status.files);\n}\n\nfunction hasUnmergedFiles(files: readonly { index: string; workingDirectory: string }[]) {\n return files.some(\n (file) => file.index.includes(\"U\") || file.workingDirectory.includes(\"U\"),\n );\n}\n\nasync function refCommit(repository: GitRepository, ref: string) {\n const value = await repository.raw([\"rev-parse\", \"--verify\", `${ref}^{commit}`]);\n const commit = value.trim();\n if (!/^[0-9a-f]{40}$/iu.test(commit)) {\n throw new GitRepositoryError(\"malformed-output\", \"ref-commit\");\n }\n return commit;\n}\n\nasync function compareRefs(\n repository: GitRepository,\n left: string,\n right: string,\n) {\n const output = await repository.raw([\n \"rev-list\",\n \"--left-right\",\n \"--count\",\n `${left}...${right}`,\n ]);\n const values = output.trim().split(/\\s+/u).map(Number);\n if (\n values.length !== 2 ||\n values.some((value) => !Number.isSafeInteger(value) || value < 0)\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"ref-relation\");\n }\n return { ahead: values[0]!, behind: values[1]! };\n}\n\nasync function safelyAdvanceLocalPrimary(\n repository: GitRepository,\n primaryBranch: string,\n primaryRemoteRef: string,\n localPrimaryCommit: string,\n) {\n await repository.raw([\n \"update-ref\",\n branchRef(primaryBranch),\n primaryRemoteRef,\n localPrimaryCommit,\n ]);\n}\n\nfunction deferred(\n branch: string | null,\n reason: SynchronizationDeferredReason,\n affectedPaths: readonly string[] = [],\n): RepositorySynchronizationResult {\n return {\n status: \"deferred\",\n branch,\n changed: false,\n pushed: false,\n affectedPaths,\n reason,\n };\n}\n\nfunction unsafe(\n branch: string | null,\n reason: SynchronizationUnsafeReason,\n options: Partial<SynchronizationBase> = {},\n): RepositorySynchronizationResult {\n return {\n status: \"unsafe\",\n branch,\n changed: options.changed ?? false,\n pushed: options.pushed ?? false,\n affectedPaths: options.affectedPaths ?? [],\n reason,\n };\n}\n\nexport async function assertIdentityBranchReady(\n repository: GitRepository,\n identityBranch: string,\n): Promise<void> {\n assertBranch(identityBranch, \"identity-branch\");\n const currentBranch = await repository.currentBranch();\n if (currentBranch === \"HEAD\" || currentBranch.length === 0) {\n throw new GitRepositoryError(\"conflict\", \"current-branch\");\n }\n if (currentBranch !== identityBranch) {\n throw new GitRepositoryError(\"conflict\", \"identity-branch\");\n }\n if (await hasUnresolvedRepositoryOperation(repository)) {\n throw new GitRepositoryError(\"conflict\", \"unresolved-operation\");\n }\n const status = await repository.status();\n if (hasUnmergedFiles(status.files)) {\n throw new GitRepositoryError(\"conflict\", \"unresolved-operation\");\n }\n}\n\n/**\n * Synchronize an identity branch from primary without checking out local\n * primary. Remote-tracking refs are the source of truth whenever a configured\n * remote is available. The result distinguishes non-blocking attention from\n * unsafe repository state so callers can keep authentication/read-only flows\n * available.\n */\nexport async function synchronizeIdentityBranch(\n repository: GitRepository,\n options: SynchronizeIdentityBranchOptions,\n): Promise<RepositorySynchronizationResult> {\n assertBranch(options.identityBranch, \"identity-branch\");\n assertBranch(options.primaryBranch, \"primary-branch\");\n assertBranch(options.remote, \"remote\");\n\n if (options.identityBranch === options.primaryBranch) {\n throw new GitRepositoryError(\"invalid-configuration\", \"identity-primary-branch\");\n }\n\n const currentBranch = await repository.currentBranch();\n if (currentBranch === \"HEAD\" || currentBranch.length === 0) {\n return unsafe(null, \"detached-head\");\n }\n\n if (await hasUnresolvedRepositoryOperation(repository)) {\n return unsafe(currentBranch, \"unresolved-operation\");\n }\n\n let status = await repository.status();\n if (hasUnmergedFiles(status.files)) {\n return unsafe(currentBranch, \"unresolved-operation\", {\n affectedPaths: status.files.map((file) => file.path),\n });\n }\n\n const configuredRemote = (await repository.remotes()).some(\n (remote) => remote.name === options.remote,\n );\n if (configuredRemote) {\n try {\n await repository.fetch(options.remote);\n } catch (error) {\n if (\n error instanceof GitRepositoryError &&\n error.kind === \"invalid-configuration\"\n ) {\n throw error;\n }\n return deferred(currentBranch, \"fetch-failed\");\n }\n }\n\n const branches = await repository.branches();\n const localPrimary = branches.all.includes(options.primaryBranch);\n const primaryRemote = remoteRef(options.remote, options.primaryBranch);\n const remotePrimary = configuredRemote && branches.all.includes(primaryRemote);\n if (configuredRemote ? !remotePrimary : !localPrimary) {\n return unsafe(currentBranch, \"missing-primary\");\n }\n\n const localIdentity = branches.all.includes(options.identityBranch);\n const identityRemote = remoteRef(options.remote, options.identityBranch);\n const remoteIdentity =\n configuredRemote && branches.all.includes(identityRemote);\n\n if (localIdentity && remoteIdentity) {\n const relation = await compareRefs(\n repository,\n options.identityBranch,\n identityRemote,\n );\n if (relation.ahead > 0 && relation.behind > 0) {\n return unsafe(currentBranch, \"identity-divergence\");\n }\n }\n\n let primaryAdvance:\n | { localCommit: string; remoteRef: string }\n | undefined;\n if (localPrimary && remotePrimary) {\n const relation = await compareRefs(\n repository,\n options.primaryBranch,\n primaryRemote,\n );\n if (relation.ahead === 0 && relation.behind > 0) {\n primaryAdvance = {\n localCommit: await refCommit(repository, options.primaryBranch),\n remoteRef: primaryRemote,\n };\n }\n }\n\n const sourceRef = remotePrimary ? primaryRemote : options.primaryBranch;\n const managedPaths = new Set(options.managedPaths ?? []);\n const managedChanges = status.files.flatMap((file) =>\n [file.path, ...(file.from === undefined ? [] : [file.from])].filter((path) =>\n managedPaths.has(path),\n ),\n );\n if (managedChanges.length > 0) {\n for (const path of managedChanges) {\n await restorePathFromRef(repository, sourceRef, path);\n }\n status = await repository.status();\n }\n const remainingDirtyPaths = status.files\n .flatMap((file) => [file.path, ...(file.from === undefined ? [] : [file.from])])\n .filter((path) => !managedPaths.has(path));\n if (remainingDirtyPaths.length > 0 || (!status.clean && status.files.length === 0)) {\n return deferred(currentBranch, \"dirty-worktree\", remainingDirtyPaths);\n }\n\n let identityCreated = false;\n if (!localIdentity) {\n identityCreated = true;\n if (remoteIdentity) {\n await repository.checkout([\n \"-b\",\n options.identityBranch,\n \"--track\",\n `${options.remote}/${options.identityBranch}`,\n ]);\n } else {\n await repository.checkout([\"-b\", options.identityBranch, sourceRef]);\n }\n } else if (currentBranch !== options.identityBranch) {\n await repository.checkout([options.identityBranch]);\n }\n\n if (primaryAdvance && currentBranch !== options.primaryBranch) {\n await safelyAdvanceLocalPrimary(\n repository,\n options.primaryBranch,\n primaryAdvance.remoteRef,\n primaryAdvance.localCommit,\n );\n }\n\n if (localIdentity && remoteIdentity) {\n const relation = await compareRefs(\n repository,\n options.identityBranch,\n identityRemote,\n );\n if (relation.ahead === 0 && relation.behind > 0) {\n await repository.merge([identityRemote, \"--ff-only\"]);\n }\n }\n\n const beforeMerge = await refCommit(repository, options.identityBranch);\n try {\n await repository.merge([sourceRef, \"--no-edit\"]);\n } catch (error) {\n if (!(error instanceof GitRepositoryError) || error.kind !== \"conflict\") {\n return unsafe(options.identityBranch, \"merge-failed\");\n }\n let affectedPaths: readonly string[] = [];\n try {\n affectedPaths = (await repository.status()).files.map((file) => file.path);\n } catch {\n // Preserve the conflict classification even if status cannot be read.\n }\n try {\n await repository.raw([\"merge\", \"--abort\"]);\n } catch {\n return unsafe(options.identityBranch, \"failed-abort\", {\n affectedPaths,\n });\n }\n return deferred(options.identityBranch, \"merge-conflict\", affectedPaths);\n }\n\n const afterMerge = await refCommit(repository, options.identityBranch);\n const changed = beforeMerge !== afterMerge;\n const mergedPaths = changed\n ? (await repository.raw([\n \"diff\",\n \"--name-only\",\n \"-z\",\n `${beforeMerge}..${afterMerge}`,\n ]))\n .split(\"\\0\")\n .filter((path) => path.length > 0)\n : [];\n const affectedPaths = [\n ...new Set([\n ...managedChanges,\n ...mergedPaths,\n ...(identityCreated ? [...managedPaths] : []),\n ]),\n ];\n if (!changed || !configuredRemote) {\n return {\n status: \"synchronized\",\n branch: options.identityBranch,\n changed,\n pushed: false,\n affectedPaths,\n };\n }\n\n try {\n await repository.push(options.remote, options.identityBranch, [\n \"--set-upstream\",\n ]);\n } catch {\n return unsafe(options.identityBranch, \"push-failed\", {\n changed,\n affectedPaths,\n });\n }\n\n return {\n status: \"synchronized\",\n branch: options.identityBranch,\n changed: true,\n pushed: true,\n affectedPaths,\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { lstat } from "node:fs/promises";
2
2
  import { isAbsolute, resolve } from "node:path";
3
- import { GitRepositoryError, } from "../git-repository.js";
3
+ import { GitRepositoryError, restorePathFromRef, } from "../git-repository.js";
4
4
  const OPERATION_MARKERS = [
5
5
  "MERGE_HEAD",
6
6
  "CHERRY_PICK_HEAD",
@@ -141,15 +141,12 @@ export async function synchronizeIdentityBranch(repository, options) {
141
141
  if (await hasUnresolvedRepositoryOperation(repository)) {
142
142
  return unsafe(currentBranch, "unresolved-operation");
143
143
  }
144
- const status = await repository.status();
144
+ let status = await repository.status();
145
145
  if (hasUnmergedFiles(status.files)) {
146
146
  return unsafe(currentBranch, "unresolved-operation", {
147
147
  affectedPaths: status.files.map((file) => file.path),
148
148
  });
149
149
  }
150
- if (!status.clean) {
151
- return deferred(currentBranch, "dirty-worktree", status.files.map((file) => file.path));
152
- }
153
150
  const configuredRemote = (await repository.remotes()).some((remote) => remote.name === options.remote);
154
151
  if (configuredRemote) {
155
152
  try {
@@ -190,7 +187,23 @@ export async function synchronizeIdentityBranch(repository, options) {
190
187
  }
191
188
  }
192
189
  const sourceRef = remotePrimary ? primaryRemote : options.primaryBranch;
190
+ const managedPaths = new Set(options.managedPaths ?? []);
191
+ const managedChanges = status.files.flatMap((file) => [file.path, ...(file.from === undefined ? [] : [file.from])].filter((path) => managedPaths.has(path)));
192
+ if (managedChanges.length > 0) {
193
+ for (const path of managedChanges) {
194
+ await restorePathFromRef(repository, sourceRef, path);
195
+ }
196
+ status = await repository.status();
197
+ }
198
+ const remainingDirtyPaths = status.files
199
+ .flatMap((file) => [file.path, ...(file.from === undefined ? [] : [file.from])])
200
+ .filter((path) => !managedPaths.has(path));
201
+ if (remainingDirtyPaths.length > 0 || (!status.clean && status.files.length === 0)) {
202
+ return deferred(currentBranch, "dirty-worktree", remainingDirtyPaths);
203
+ }
204
+ let identityCreated = false;
193
205
  if (!localIdentity) {
206
+ identityCreated = true;
194
207
  if (remoteIdentity) {
195
208
  await repository.checkout([
196
209
  "-b",
@@ -242,13 +255,30 @@ export async function synchronizeIdentityBranch(repository, options) {
242
255
  }
243
256
  const afterMerge = await refCommit(repository, options.identityBranch);
244
257
  const changed = beforeMerge !== afterMerge;
258
+ const mergedPaths = changed
259
+ ? (await repository.raw([
260
+ "diff",
261
+ "--name-only",
262
+ "-z",
263
+ `${beforeMerge}..${afterMerge}`,
264
+ ]))
265
+ .split("\0")
266
+ .filter((path) => path.length > 0)
267
+ : [];
268
+ const affectedPaths = [
269
+ ...new Set([
270
+ ...managedChanges,
271
+ ...mergedPaths,
272
+ ...(identityCreated ? [...managedPaths] : []),
273
+ ]),
274
+ ];
245
275
  if (!changed || !configuredRemote) {
246
276
  return {
247
277
  status: "synchronized",
248
278
  branch: options.identityBranch,
249
279
  changed,
250
280
  pushed: false,
251
- affectedPaths: [],
281
+ affectedPaths,
252
282
  };
253
283
  }
254
284
  try {
@@ -257,14 +287,17 @@ export async function synchronizeIdentityBranch(repository, options) {
257
287
  ]);
258
288
  }
259
289
  catch {
260
- return unsafe(options.identityBranch, "push-failed", { changed });
290
+ return unsafe(options.identityBranch, "push-failed", {
291
+ changed,
292
+ affectedPaths,
293
+ });
261
294
  }
262
295
  return {
263
296
  status: "synchronized",
264
297
  branch: options.identityBranch,
265
298
  changed: true,
266
299
  pushed: true,
267
- affectedPaths: [],
300
+ affectedPaths,
268
301
  };
269
302
  }
270
303
  //# sourceMappingURL=repository-synchronization.js.map