fix: create repos despite commit signing
This commit is contained in:
@@ -443,6 +443,8 @@ On first launch, `useOnboarding` checks if the default vault exists. If not, it
|
|||||||
- **Open an existing folder** → system file picker
|
- **Open an existing folder** → system file picker
|
||||||
- **Get started with a template** → pick a parent folder, then call `create_getting_started_vault()` with the derived `.../Getting Started` child path so the cloned vault opens into the populated repo root immediately
|
- **Get started with a template** → pick a parent folder, then call `create_getting_started_vault()` with the derived `.../Getting Started` child path so the cloned vault opens into the populated repo root immediately
|
||||||
|
|
||||||
|
When an opened folder is not yet a git repo, `init_git_repo` runs `git init`, ensures Tolaria's default `.gitignore`, stages the vault, and writes the initial `Initial vault setup` commit. That app-managed setup commit explicitly disables commit signing for the single command so inherited global or local `commit.gpgsign` preferences cannot strand onboarding when GPG is missing or misconfigured.
|
||||||
|
|
||||||
Once a vault is ready, `useAiAgentsOnboarding` can show a one-time `AiAgentsOnboardingPrompt`. That prompt reads `useAiAgentsStatus` so first launch surfaces whether Claude Code and Codex are installed, offers per-agent install links when they are missing, and stores local dismissal so the prompt does not repeat on every launch.
|
Once a vault is ready, `useAiAgentsOnboarding` can show a one-time `AiAgentsOnboardingPrompt`. That prompt reads `useAiAgentsStatus` so first launch surfaces whether Claude Code and Codex are installed, offers per-agent install links when they are missing, and stores local dismissal so the prompt does not repeat on every launch.
|
||||||
|
|
||||||
`useGettingStartedClone` reuses the same parent-folder semantics for the status-bar / command-palette clone action, and `Toast` is rendered through the AI-agents onboarding gate so the resolved destination path stays visible right after a successful clone.
|
`useGettingStartedClone` reuses the same parent-folder semantics for the status-bar / command-palette clone action, and `Toast` is rendered through the AI-agents onboarding gate so the resolved destination path stays visible right after a successful clone.
|
||||||
@@ -648,6 +650,7 @@ The vault backend (`src-tauri/src/vault/`) is split into focused submodules:
|
|||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
|
| `init_git_repo` | Initialize a local repo, add default `.gitignore`, and create the unsigned setup commit |
|
||||||
| `git_commit` | Stage all + commit |
|
| `git_commit` | Stage all + commit |
|
||||||
| `git_pull` | Pull from remote |
|
| `git_pull` | Pull from remote |
|
||||||
| `git_push` | Push to remote |
|
| `git_push` | Push to remote |
|
||||||
|
|||||||
@@ -79,18 +79,31 @@ pub fn init_repo(path: &str) -> Result<(), String> {
|
|||||||
ensure_gitignore(path)?;
|
ensure_gitignore(path)?;
|
||||||
|
|
||||||
run_git(dir, &["add", "."])?;
|
run_git(dir, &["add", "."])?;
|
||||||
run_git(dir, &["commit", "-m", "Initial vault setup"])?;
|
commit_initial_vault_setup(dir)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn commit_initial_vault_setup(dir: &Path) -> Result<(), String> {
|
||||||
|
run_git(
|
||||||
|
dir,
|
||||||
|
&[
|
||||||
|
"-c",
|
||||||
|
"commit.gpgsign=false",
|
||||||
|
"commit",
|
||||||
|
"-m",
|
||||||
|
"Initial vault setup",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Run a git command in the given directory, returning an error on failure.
|
/// Run a git command in the given directory, returning an error on failure.
|
||||||
fn run_git(dir: &Path, args: &[&str]) -> Result<(), String> {
|
fn run_git(dir: &Path, args: &[&str]) -> Result<(), String> {
|
||||||
let output = Command::new("git")
|
let output = Command::new("git")
|
||||||
.args(args)
|
.args(args)
|
||||||
.current_dir(dir)
|
.current_dir(dir)
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("Failed to run git {}: {}", args[0], e))?;
|
.map_err(|e| format!("Failed to run git {}: {e}", git_command_label(args)))?;
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -98,11 +111,19 @@ fn run_git(dir: &Path, args: &[&str]) -> Result<(), String> {
|
|||||||
|
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"git {} failed: {}",
|
"git {} failed: {}",
|
||||||
args[0],
|
git_command_label(args),
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&output.stderr)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn git_command_label<'a>(args: &'a [&'a str]) -> &'a str {
|
||||||
|
if args.first() == Some(&"-c") {
|
||||||
|
return args.get(2).copied().unwrap_or(args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
args[0]
|
||||||
|
}
|
||||||
|
|
||||||
/// Set local user.name and user.email if not already configured.
|
/// Set local user.name and user.email if not already configured.
|
||||||
fn ensure_author_config(dir: &Path) -> Result<(), String> {
|
fn ensure_author_config(dir: &Path) -> Result<(), String> {
|
||||||
for (key, fallback) in [
|
for (key, fallback) in [
|
||||||
@@ -289,6 +310,39 @@ mod tests {
|
|||||||
assert!(log_str.contains("Initial vault setup"));
|
assert!(log_str.contains("Initial vault setup"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_init_repo_creates_initial_commit_when_signing_is_misconfigured() {
|
||||||
|
let dir = TempDir::new().unwrap();
|
||||||
|
let vault = dir.path().join("new-vault");
|
||||||
|
fs::create_dir_all(&vault).unwrap();
|
||||||
|
fs::write(vault.join("note.md"), "# Test\n").unwrap();
|
||||||
|
|
||||||
|
Command::new("git")
|
||||||
|
.args(["init"])
|
||||||
|
.current_dir(&vault)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
Command::new("git")
|
||||||
|
.args(["config", "commit.gpgsign", "true"])
|
||||||
|
.current_dir(&vault)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
Command::new("git")
|
||||||
|
.args(["config", "gpg.program", "/missing/tolaria-test-gpg"])
|
||||||
|
.current_dir(&vault)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
init_repo(vault.to_str().unwrap()).unwrap();
|
||||||
|
|
||||||
|
let log = Command::new("git")
|
||||||
|
.args(["log", "--oneline"])
|
||||||
|
.current_dir(&vault)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(String::from_utf8_lossy(&log.stdout).contains("Initial vault setup"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_init_repo_stages_all_files() {
|
fn test_init_repo_stages_all_files() {
|
||||||
let dir = TempDir::new().unwrap();
|
let dir = TempDir::new().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user