Skip to content

Commit 9f86c69

Browse files
CopilotByron
andcommitted
Add git repository initialization functionality and enhanced error handling
Co-authored-by: Byron <[email protected]>
1 parent 90ef91f commit 9f86c69

File tree

4 files changed

+72
-2
lines changed

4 files changed

+72
-2
lines changed

apps/desktop/src/lib/project/projectsService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ export class ProjectsService {
137137
unsetLastOpenedProject() {
138138
this.persistedId.set(undefined);
139139
}
140+
141+
async initGitRepository(path: string): Promise<void> {
142+
return await this.backend.invoke('init_git_repository', { path });
143+
}
140144
}
141145

142146
function injectEndpoints(api: ClientState['backendApi']) {

apps/desktop/src/routes/[projectId]/+layout.svelte

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import ReduxResult from '$components/ReduxResult.svelte';
1313
import { OnboardingEvent, POSTHOG_WRAPPER } from '$lib/analytics/posthog';
1414
import { BACKEND } from '$lib/backend';
15+
import { getUserErrorCode, Code } from '$lib/backend/ipc';
1516
import { BASE_BRANCH_SERVICE } from '$lib/baseBranch/baseBranchService.svelte';
1617
import { BRANCH_SERVICE } from '$lib/branches/branchService.svelte';
1718
import { SETTINGS_SERVICE } from '$lib/config/appSettingsV2';
@@ -22,7 +23,7 @@
2223
import { GITLAB_STATE } from '$lib/forge/gitlab/gitlabState.svelte';
2324
import { GIT_SERVICE } from '$lib/git/gitService';
2425
import { MODE_SERVICE } from '$lib/mode/modeService';
25-
import { showError, showInfo, showWarning } from '$lib/notifications/toasts';
26+
import { showError, showInfo, showWarning, showToast } from '$lib/notifications/toasts';
2627
import { PROJECTS_SERVICE } from '$lib/project/projectsService';
2728
import { FILE_SELECTION_MANAGER } from '$lib/selection/fileSelectionManager.svelte';
2829
import { UNCOMMITTED_SERVICE } from '$lib/selection/uncommittedService.svelte';
@@ -320,7 +321,44 @@
320321
}
321322
} catch (error: unknown) {
322323
posthog.captureOnboarding(OnboardingEvent.SetProjectActiveFailed);
323-
showError('Failed to set the project active', error);
324+
325+
// Check if this is a non-git repository error
326+
const errorCode = getUserErrorCode(error);
327+
if (errorCode === Code.NonGitRepository) {
328+
// Show special toast with git init option
329+
showToast({
330+
title: 'Not a Git repository',
331+
message: 'The selected directory is not a Git repository. Would you like to initialize one?',
332+
style: 'warning',
333+
extraAction: {
334+
label: 'Initialize Repository',
335+
onClick: async (dismiss) => {
336+
try {
337+
const currentProject = projects?.find((p) => p.id === projectId);
338+
if (currentProject?.path) {
339+
await projectsService.initGitRepository(currentProject.path);
340+
dismiss();
341+
showToast({
342+
title: 'Repository Initialized',
343+
message: 'Git repository has been initialized successfully. Retrying...',
344+
style: 'info'
345+
});
346+
// Retry setting the project active
347+
await setActiveProjectOrRedirect(projectId);
348+
} else {
349+
throw new Error('Could not find project path');
350+
}
351+
} catch (initError) {
352+
console.error('Failed to initialize repository:', initError);
353+
dismiss();
354+
showError('Failed to initialize repository', initError);
355+
}
356+
}
357+
}
358+
});
359+
} else {
360+
showError('Failed to set the project active', error);
361+
}
324362
}
325363
}
326364

crates/gitbutler-tauri/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ fn main() {
227227
projects::list_projects,
228228
projects::set_project_active,
229229
projects::open_project_in_window,
230+
projects::init_git_repository,
230231
repo::git_get_local_config,
231232
repo::git_set_local_config,
232233
repo::check_signing_settings,

crates/gitbutler-tauri/src/projects.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,30 @@ Ensure these aren't touched by GitButler or avoid using it in this repository.",
216216
}
217217
Ok(Some(msg))
218218
}
219+
220+
/// Initialize a Git repository at the given path
221+
#[tauri::command]
222+
#[instrument(err(Debug))]
223+
pub fn init_git_repository(path: String) -> Result<(), Error> {
224+
let repo_path = std::path::Path::new(&path);
225+
226+
// Check if path exists and is a directory
227+
if !repo_path.exists() {
228+
return Err(anyhow::anyhow!("Path does not exist: {}", path).into());
229+
}
230+
if !repo_path.is_dir() {
231+
return Err(anyhow::anyhow!("Path is not a directory: {}", path).into());
232+
}
233+
234+
// Check if it's already a git repository
235+
if git2::Repository::open(repo_path).is_ok() {
236+
return Err(anyhow::anyhow!("Directory is already a Git repository").into());
237+
}
238+
239+
// Initialize the repository
240+
git2::Repository::init(repo_path)
241+
.with_context(|| format!("Failed to initialize Git repository at {}", path))?;
242+
243+
tracing::info!("Successfully initialized Git repository at {}", path);
244+
Ok(())
245+
}

0 commit comments

Comments
 (0)