git: Implement commit creation (#23263)

- [x] Basic implementation
- [x] Disable commit buttons when committing is not possible (empty
message, no changes)
- [x] Upgrade GitSummary to efficiently figure out whether there are any
staged changes
- [x] Make CommitAll work
- [x] Surface errors with toasts
  - [x] Channel shutdown
  - [x] Empty commit message or no changes
  - [x] Failed git operations
- [x] Fix added files no longer appearing correctly in the project panel
(GitSummary breakage)
- [x] Fix handling of commit message

Release Notes:

- N/A

---------

Co-authored-by: Nate <nate@zed.dev>
This commit is contained in:
Cole Miller 2025-01-17 13:51:20 -05:00 committed by GitHub
parent 3767e7e5f0
commit 5da67899b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 387 additions and 198 deletions

View file

@ -61,6 +61,8 @@ pub trait GitRepository: Send + Sync {
///
/// If any of the paths were previously staged but do not exist in HEAD, they will be removed from the index.
fn unstage_paths(&self, paths: &[RepoPath]) -> Result<()>;
fn commit(&self, message: &str) -> Result<()>;
}
impl std::fmt::Debug for dyn GitRepository {
@ -280,6 +282,24 @@ impl GitRepository for RealGitRepository {
}
Ok(())
}
fn commit(&self, message: &str) -> Result<()> {
let working_directory = self
.repository
.lock()
.workdir()
.context("failed to read git work directory")?
.to_path_buf();
let cmd = new_std_command(&self.git_binary_path)
.current_dir(&working_directory)
.args(["commit", "--quiet", "-m", message])
.status()?;
if !cmd.success() {
return Err(anyhow!("Failed to commit: {cmd}"));
}
Ok(())
}
}
#[derive(Debug, Clone)]
@ -423,6 +443,10 @@ impl GitRepository for FakeGitRepository {
fn unstage_paths(&self, _paths: &[RepoPath]) -> Result<()> {
unimplemented!()
}
fn commit(&self, _message: &str) -> Result<()> {
unimplemented!()
}
}
fn check_path_to_repo_path_errors(relative_file_path: &Path) -> Result<()> {