Better private file sharing for remote projects (#12002)
Release Notes: - N/A --------- Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
3a79aa85f4
commit
1732ea95c2
2 changed files with 41 additions and 35 deletions
|
@ -3,16 +3,13 @@ use client::DevServerProjectId;
|
||||||
use client::{user::UserStore, Client, ClientSettings};
|
use client::{user::UserStore, Client, ClientSettings};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use gpui::{
|
use gpui::{AppContext, AsyncAppContext, Context, Global, Model, ModelContext, Task, WeakModel};
|
||||||
AppContext, AsyncAppContext, Context, Global, Model, ModelContext, Task, UpdateGlobal,
|
|
||||||
WeakModel,
|
|
||||||
};
|
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use postage::stream::Stream;
|
use postage::stream::Stream;
|
||||||
use project::{Project, WorktreeSettings};
|
use project::Project;
|
||||||
use rpc::{proto, ErrorCode, TypedEnvelope};
|
use rpc::{proto, ErrorCode, TypedEnvelope};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::Settings;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
use util::{ResultExt, TryFutureExt};
|
use util::{ResultExt, TryFutureExt};
|
||||||
|
|
||||||
|
@ -40,15 +37,6 @@ pub fn init(client: Arc<Client>, app_state: AppState, cx: &mut AppContext) -> Ta
|
||||||
let dev_server = cx.new_model(|cx| DevServer::new(client.clone(), app_state, cx));
|
let dev_server = cx.new_model(|cx| DevServer::new(client.clone(), app_state, cx));
|
||||||
cx.set_global(GlobalDevServer(dev_server.clone()));
|
cx.set_global(GlobalDevServer(dev_server.clone()));
|
||||||
|
|
||||||
// Dev server cannot have any private files for now
|
|
||||||
SettingsStore::update_global(cx, |store, _cx| {
|
|
||||||
let old_settings = store.get::<WorktreeSettings>(None);
|
|
||||||
store.override_global(WorktreeSettings {
|
|
||||||
private_files: Some(vec![]),
|
|
||||||
..old_settings.clone()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
{
|
{
|
||||||
use signal_hook::consts::{SIGINT, SIGTERM};
|
use signal_hook::consts::{SIGINT, SIGTERM};
|
||||||
|
@ -229,12 +217,16 @@ impl DevServer {
|
||||||
|
|
||||||
let path = shellexpand::tilde(&dev_server_project.path).to_string();
|
let path = shellexpand::tilde(&dev_server_project.path).to_string();
|
||||||
|
|
||||||
project
|
let (worktree, _) = project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
project.find_or_create_local_worktree(&path, true, cx)
|
project.find_or_create_local_worktree(&path, true, cx)
|
||||||
})?
|
})?
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
worktree.update(cx, |worktree, cx| {
|
||||||
|
worktree.as_local_mut().unwrap().share_private_files(cx)
|
||||||
|
})?;
|
||||||
|
|
||||||
let worktrees =
|
let worktrees =
|
||||||
project.read_with(cx, |project, cx| project.worktree_metadata_protos(cx))?;
|
project.read_with(cx, |project, cx| project.worktree_metadata_protos(cx))?;
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,8 @@ pub struct LocalWorktree {
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
fs_case_sensitive: bool,
|
fs_case_sensitive: bool,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
|
|
||||||
|
next_entry_id: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScanRequest {
|
struct ScanRequest {
|
||||||
|
@ -285,6 +287,7 @@ pub struct LocalSnapshot {
|
||||||
git_repositories: TreeMap<ProjectEntryId, LocalRepositoryEntry>,
|
git_repositories: TreeMap<ProjectEntryId, LocalRepositoryEntry>,
|
||||||
file_scan_exclusions: Vec<PathMatcher>,
|
file_scan_exclusions: Vec<PathMatcher>,
|
||||||
private_files: Vec<PathMatcher>,
|
private_files: Vec<PathMatcher>,
|
||||||
|
share_private_files: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BackgroundScannerState {
|
struct BackgroundScannerState {
|
||||||
|
@ -381,9 +384,6 @@ impl Worktree {
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
let closure_fs = Arc::clone(&fs);
|
|
||||||
let closure_next_entry_id = Arc::clone(&next_entry_id);
|
|
||||||
let closure_abs_path = abs_path.to_path_buf();
|
|
||||||
cx.new_model(move |cx: &mut ModelContext<Worktree>| {
|
cx.new_model(move |cx: &mut ModelContext<Worktree>| {
|
||||||
cx.observe_global::<SettingsStore>(move |this, cx| {
|
cx.observe_global::<SettingsStore>(move |this, cx| {
|
||||||
if let Self::Local(this) = this {
|
if let Self::Local(this) = this {
|
||||||
|
@ -421,21 +421,7 @@ impl Worktree {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
|
|
||||||
let (scan_requests_tx, scan_requests_rx) = channel::unbounded();
|
this.restart_background_scanners(cx);
|
||||||
let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) =
|
|
||||||
channel::unbounded();
|
|
||||||
this.scan_requests_tx = scan_requests_tx;
|
|
||||||
this.path_prefixes_to_scan_tx = path_prefixes_to_scan_tx;
|
|
||||||
this._background_scanner_tasks = start_background_scan_tasks(
|
|
||||||
&closure_abs_path,
|
|
||||||
this.snapshot(),
|
|
||||||
scan_requests_rx,
|
|
||||||
path_prefixes_to_scan_rx,
|
|
||||||
Arc::clone(&closure_next_entry_id),
|
|
||||||
Arc::clone(&closure_fs),
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
this.is_scanning = watch::channel_with(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -459,6 +445,7 @@ impl Worktree {
|
||||||
}), cx).private_files.as_deref(),
|
}), cx).private_files.as_deref(),
|
||||||
"private_files",
|
"private_files",
|
||||||
),
|
),
|
||||||
|
share_private_files: false,
|
||||||
ignores_by_parent_abs_path: Default::default(),
|
ignores_by_parent_abs_path: Default::default(),
|
||||||
git_repositories: Default::default(),
|
git_repositories: Default::default(),
|
||||||
snapshot: Snapshot {
|
snapshot: Snapshot {
|
||||||
|
@ -490,6 +477,7 @@ impl Worktree {
|
||||||
let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) = channel::unbounded();
|
let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) = channel::unbounded();
|
||||||
let task_snapshot = snapshot.clone();
|
let task_snapshot = snapshot.clone();
|
||||||
Worktree::Local(LocalWorktree {
|
Worktree::Local(LocalWorktree {
|
||||||
|
next_entry_id: Arc::clone(&next_entry_id),
|
||||||
snapshot,
|
snapshot,
|
||||||
is_scanning: watch::channel_with(true),
|
is_scanning: watch::channel_with(true),
|
||||||
share: None,
|
share: None,
|
||||||
|
@ -949,14 +937,32 @@ impl LocalWorktree {
|
||||||
Ok(!old_summary.is_empty() || !new_summary.is_empty())
|
Ok(!old_summary.is_empty() || !new_summary.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restart_background_scanners(&mut self, cx: &mut ModelContext<Worktree>) {
|
||||||
|
let (scan_requests_tx, scan_requests_rx) = channel::unbounded();
|
||||||
|
let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) = channel::unbounded();
|
||||||
|
self.scan_requests_tx = scan_requests_tx;
|
||||||
|
self.path_prefixes_to_scan_tx = path_prefixes_to_scan_tx;
|
||||||
|
self._background_scanner_tasks = start_background_scan_tasks(
|
||||||
|
&self.snapshot.abs_path,
|
||||||
|
self.snapshot(),
|
||||||
|
scan_requests_rx,
|
||||||
|
path_prefixes_to_scan_rx,
|
||||||
|
Arc::clone(&self.next_entry_id),
|
||||||
|
Arc::clone(&self.fs),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
self.is_scanning = watch::channel_with(true);
|
||||||
|
}
|
||||||
|
|
||||||
fn set_snapshot(
|
fn set_snapshot(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_snapshot: LocalSnapshot,
|
mut new_snapshot: LocalSnapshot,
|
||||||
entry_changes: UpdatedEntriesSet,
|
entry_changes: UpdatedEntriesSet,
|
||||||
cx: &mut ModelContext<Worktree>,
|
cx: &mut ModelContext<Worktree>,
|
||||||
) {
|
) {
|
||||||
let repo_changes = self.changed_repos(&self.snapshot, &new_snapshot);
|
let repo_changes = self.changed_repos(&self.snapshot, &new_snapshot);
|
||||||
|
|
||||||
|
new_snapshot.share_private_files = self.snapshot.share_private_files;
|
||||||
self.snapshot = new_snapshot;
|
self.snapshot = new_snapshot;
|
||||||
|
|
||||||
if let Some(share) = self.share.as_mut() {
|
if let Some(share) = self.share.as_mut() {
|
||||||
|
@ -1663,6 +1669,11 @@ impl LocalWorktree {
|
||||||
pub fn is_shared(&self) -> bool {
|
pub fn is_shared(&self) -> bool {
|
||||||
self.share.is_some()
|
self.share.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn share_private_files(&mut self, cx: &mut ModelContext<Worktree>) {
|
||||||
|
self.snapshot.share_private_files = true;
|
||||||
|
self.restart_background_scanners(cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteWorktree {
|
impl RemoteWorktree {
|
||||||
|
@ -2517,6 +2528,9 @@ impl LocalSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_path_private(&self, path: &Path) -> bool {
|
pub fn is_path_private(&self, path: &Path) -> bool {
|
||||||
|
if self.share_private_files {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
path.ancestors().any(|ancestor| {
|
path.ancestors().any(|ancestor| {
|
||||||
self.private_files
|
self.private_files
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue