diff --git a/cli/src/commands/git.rs b/cli/src/commands/git.rs index b56b29388..91b9c6f76 100644 --- a/cli/src/commands/git.rs +++ b/cli/src/commands/git.rs @@ -1,5 +1,5 @@ use std::collections::HashSet; -use std::io::{Read, Seek as _, SeekFrom, Write}; +use std::io::{Read, Write}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -210,43 +210,19 @@ fn map_git_error(err: git2::Error) -> CommandError { } } -pub fn add_to_git_exclude(ui: &Ui, git_repo: &git2::Repository) -> Result<(), CommandError> { - let exclude_file_path = git_repo.path().join("info").join("exclude"); - if exclude_file_path.exists() { - match fs::OpenOptions::new() - .read(true) - .write(true) - .open(&exclude_file_path) - { - Ok(mut exclude_file) => { - let mut buf = vec![]; - exclude_file.read_to_end(&mut buf)?; - let pattern = b"\n/.jj/\n"; - if !buf.windows(pattern.len()).any(|window| window == pattern) { - exclude_file.seek(SeekFrom::End(0))?; - if !buf.ends_with(b"\n") { - exclude_file.write_all(b"\n")?; - } - exclude_file.write_all(b"/.jj/\n")?; - } - } - Err(err) => { - writeln!( - ui.error(), - "Failed to add `.jj/` to {}: {}", - exclude_file_path.to_string_lossy(), - err - )?; - } - } +pub fn maybe_add_gitignore(workspace_command: &WorkspaceCommandHelper) -> Result<(), CommandError> { + if workspace_command.working_copy_shared_with_git() { + std::fs::write( + workspace_command + .workspace_root() + .join(".jj") + .join(".gitignore"), + "/*\n", + ) + .map_err(|e| user_error(format!("Failed to write .jj/.gitignore file: {e}"))) } else { - writeln!( - ui.error(), - "Failed to add `.jj/` to {} because it doesn't exist", - exclude_file_path.to_string_lossy() - )?; + Ok(()) } - Ok(()) } fn cmd_git_remote_add( @@ -525,7 +501,6 @@ fn do_git_clone( ) -> Result<(WorkspaceCommandHelper, GitFetchStats), CommandError> { let (workspace, repo) = if colocate { let git_repo = git2::Repository::init(wc_path)?; - add_to_git_exclude(ui, &git_repo)?; Workspace::init_external_git(command.settings(), wc_path, git_repo.path())? } else { Workspace::init_internal_git(command.settings(), wc_path)? @@ -537,6 +512,7 @@ fn do_git_clone( wc_path.display() )?; let mut workspace_command = command.for_loaded_repo(ui, workspace, repo)?; + maybe_add_gitignore(&workspace_command)?; git_repo.remote(remote_name, source).unwrap(); let mut fetch_tx = workspace_command.start_transaction("fetch from git remote into empty repo"); diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index d703175da..6ad313b29 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -1213,10 +1213,9 @@ fn cmd_init(ui: &mut Ui, command: &CommandHelper, args: &InitArgs) -> Result<(), .unwrap() .open_git_repo()?; let mut workspace_command = command.for_loaded_repo(ui, workspace, repo)?; + git::maybe_add_gitignore(&workspace_command)?; workspace_command.snapshot(ui)?; - if workspace_command.working_copy_shared_with_git() { - git::add_to_git_exclude(ui, &git_repo)?; - } else { + if !workspace_command.working_copy_shared_with_git() { let mut tx = workspace_command.start_transaction("import git refs"); let stats = jj_lib::git::import_some_refs( tx.mut_repo(), diff --git a/cli/tests/test_git_clone.rs b/cli/tests/test_git_clone.rs index c741e6cf6..62d2b4bd1 100644 --- a/cli/tests/test_git_clone.rs +++ b/cli/tests/test_git_clone.rs @@ -224,7 +224,9 @@ fn test_git_clone_colocate() { .map(|entry| format!("{:?} {}\n", entry.status(), entry.path().unwrap())) .collect(); insta::assert_snapshot!(git_statuses, @r###" - IGNORED .jj/ + IGNORED .jj/.gitignore + IGNORED .jj/repo/ + IGNORED .jj/working_copy/ "###); // The old default branch "master" shouldn't exist.