Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ tempfile.workspace = true
text.workspace = true
time.workspace = true
util.workspace = true
is_executable = "1.0.5"

[target.'cfg(target_os = "macos")'.dependencies]
fsevent.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/fs/src/fake_git_repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl GitRepository for FakeGitRepository {
path: RepoPath,
content: Option<String>,
_env: Arc<HashMap<String, String>>,
_is_executable: bool,
) -> BoxFuture<'_, anyhow::Result<()>> {
self.with_state_async(true, move |state| {
if let Some(message) = &state.simulated_index_write_error_message {
Expand Down
7 changes: 7 additions & 0 deletions crates/fs/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::mem::MaybeUninit;
use async_tar::Archive;
use futures::{AsyncRead, Stream, StreamExt, future::BoxFuture};
use git::repository::{GitRepository, RealGitRepository};
use is_executable::IsExecutable;
use rope::Rope;
use serde::{Deserialize, Serialize};
use smol::io::AsyncWriteExt;
Expand Down Expand Up @@ -208,6 +209,7 @@ pub struct Metadata {
pub is_dir: bool,
pub len: u64,
pub is_fifo: bool,
pub is_executable: bool,
}

/// Filesystem modification time. The purpose of this newtype is to discourage use of operations
Expand Down Expand Up @@ -895,13 +897,16 @@ impl Fs for RealFs {
#[cfg(unix)]
let is_fifo = metadata.file_type().is_fifo();

let is_executable = path.is_executable();
Comment thread
kubkon marked this conversation as resolved.
Resolved

Ok(Some(Metadata {
inode,
mtime: MTime(metadata.modified().unwrap_or(SystemTime::UNIX_EPOCH)),
len: metadata.len(),
is_symlink,
is_dir: metadata.file_type().is_dir(),
is_fifo,
is_executable,
}))
}

Expand Down Expand Up @@ -2602,6 +2607,7 @@ impl Fs for FakeFs {
is_dir: false,
is_symlink,
is_fifo: false,
is_executable: false,
},
FakeFsEntry::Dir {
inode, mtime, len, ..
Expand All @@ -2612,6 +2618,7 @@ impl Fs for FakeFs {
is_dir: true,
is_symlink,
is_fifo: false,
is_executable: false,
},
FakeFsEntry::Symlink { .. } => unreachable!(),
}))
Expand Down
6 changes: 5 additions & 1 deletion crates/git/src/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ pub trait GitRepository: Send + Sync {
path: RepoPath,
content: Option<String>,
env: Arc<HashMap<String, String>>,
is_executable: bool,
) -> BoxFuture<'_, anyhow::Result<()>>;

/// Returns the URL of the remote with the given name.
Expand Down Expand Up @@ -987,12 +988,15 @@ impl GitRepository for RealGitRepository {
path: RepoPath,
content: Option<String>,
env: Arc<HashMap<String, String>>,
is_executable: bool,
) -> BoxFuture<'_, anyhow::Result<()>> {
let working_directory = self.working_directory();
let git_binary_path = self.any_git_binary_path.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
let mode = if is_executable { "100755" } else { "100644" }.to_string();
Comment thread
kubkon marked this conversation as resolved.
Resolved

if let Some(content) = content {
let mut child = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
Expand All @@ -1013,7 +1017,7 @@ impl GitRepository for RealGitRepository {
let output = new_smol_command(&git_binary_path)
.current_dir(&working_directory)
.envs(env.iter())
.args(["update-index", "--add", "--cacheinfo", "100644", sha])
.args(["update-index", "--add", "--cacheinfo", &mode, sha])
Comment thread
kubkon marked this conversation as resolved.
Resolved
.arg(path.as_unix_str())
.output()
.await?;
Expand Down
15 changes: 13 additions & 2 deletions crates/project/src/git_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ impl std::ops::Deref for Repository {
#[derive(Clone)]
pub enum RepositoryState {
Local {
fs: Arc<dyn Fs>,
backend: Arc<dyn GitRepository>,
environment: Arc<HashMap<String, String>>,
},
Expand Down Expand Up @@ -4288,6 +4289,7 @@ impl Repository {
RepositoryState::Local {
backend,
environment,
..
} => backend.run_hook(hook, environment.clone()).await,
RepositoryState::Remote { project_id, client } => {
client
Expand Down Expand Up @@ -4580,6 +4582,7 @@ impl Repository {
let id = self.id;
let this = cx.weak_entity();
let git_store = self.git_store.clone();
let abs_path = self.snapshot.repo_path_to_abs_path(&path);
self.send_keyed_job(
Some(GitJobKey::WriteIndex(vec![path.clone()])),
None,
Expand All @@ -4588,14 +4591,21 @@ impl Repository {
"start updating index text for buffer {}",
path.as_unix_str()
);

match git_repo {
RepositoryState::Local {
fs,
backend,
environment,
..
} => {
let executable = match fs.metadata(&abs_path).await {
Ok(Some(meta)) => meta.is_executable,
Ok(None) => false,
Err(_err) => false,
};
backend
.set_index_text(path.clone(), content, environment.clone())
.set_index_text(path.clone(), content, environment.clone(), executable)
.await?;
}
RepositoryState::Remote { project_id, client } => {
Expand Down Expand Up @@ -5164,6 +5174,7 @@ impl Repository {
cx: &mut Context<Self>,
) -> mpsc::UnboundedSender<GitJob> {
let (job_tx, mut job_rx) = mpsc::unbounded::<GitJob>();
let fs_clone = fs.clone();
Comment thread
kubkon marked this conversation as resolved.
Resolved

cx.spawn(async move |_, cx| {
let environment = project_environment
Expand Down Expand Up @@ -5195,8 +5206,8 @@ impl Repository {
backend.clone(),
);
}

let state = RepositoryState::Local {
fs: fs_clone,
Comment thread
kubkon marked this conversation as resolved.
Resolved
backend,
environment: Arc::new(environment),
};
Expand Down
Loading