createForIssue method
Creates or reuses the workspace for issueIdentifier.
Implementation
Future<Workspace> createForIssue(String issueIdentifier) async {
final key = sanitizeKey(issueIdentifier);
if (key.isEmpty) {
throw const WorkspaceException(
WorkspaceFailureCode.emptyKey,
'Workspace key resolved to an empty string after sanitization.',
);
}
final root = p.normalize(workspaceConfig.root);
final path = resolvePath(issueIdentifier);
final branchName = 'spectra/$key';
Directory(root).createSync(recursive: true);
final dir = Directory(path);
final existedBefore = dir.existsSync();
var createdNow = false;
if (!existedBefore) {
if (useGitWorktrees) {
final result = await _git(<String>[
'worktree',
'add',
'-B',
branchName,
path,
baseRef,
], workingDirectory: repositoryRoot);
if (result.exitCode != 0) {
throw WorkspaceException(
WorkspaceFailureCode.worktreeAddFailed,
'git worktree add failed (exit ${result.exitCode}): ${result.stderr}',
);
}
} else {
try {
dir.createSync(recursive: true);
} catch (e) {
throw WorkspaceException(
WorkspaceFailureCode.createFailed,
'Failed to create workspace directory $path: $e',
cause: e,
);
}
}
createdNow = true;
}
final workspace = Workspace(
workspaceKey: key,
path: path,
branchName: branchName,
createdNow: createdNow,
);
if (createdNow) {
final outcome = await hookRunner.run(
kind: WorkspaceHookKind.afterCreate,
workspacePath: path,
hooks: hooksConfig,
);
if (outcome.isFatal) {
await _bestEffortRemoveWorktree(path);
throw WorkspaceException(
outcome.timedOut
? WorkspaceFailureCode.hookTimedOut
: WorkspaceFailureCode.hookFailed,
'after_create hook failed: ${outcome.output}',
);
}
}
return workspace;
}