worktree.rs

   1use super::{
   2    fs::{self, Fs},
   3    ignore::IgnoreStack,
   4};
   5use ::ignore::gitignore::{Gitignore, GitignoreBuilder};
   6use anyhow::{anyhow, Context, Result};
   7use client::{proto, Client, PeerId, TypedEnvelope};
   8use clock::ReplicaId;
   9use futures::{Stream, StreamExt};
  10use fuzzy::CharBag;
  11use gpui::{
  12    executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
  13    Task, UpgradeModelHandle, WeakModelHandle,
  14};
  15use language::{Buffer, Language, LanguageRegistry, Operation, Rope};
  16use lazy_static::lazy_static;
  17use lsp::LanguageServer;
  18use parking_lot::Mutex;
  19use postage::{
  20    prelude::{Sink as _, Stream as _},
  21    watch,
  22};
  23
  24use serde::Deserialize;
  25use smol::channel::{self, Sender};
  26use std::{
  27    any::Any,
  28    cmp::{self, Ordering},
  29    collections::HashMap,
  30    convert::{TryFrom, TryInto},
  31    ffi::{OsStr, OsString},
  32    fmt,
  33    future::Future,
  34    ops::Deref,
  35    path::{Path, PathBuf},
  36    sync::{
  37        atomic::{AtomicUsize, Ordering::SeqCst},
  38        Arc,
  39    },
  40    time::{Duration, SystemTime},
  41};
  42use sum_tree::Bias;
  43use sum_tree::{Edit, SeekTarget, SumTree};
  44use util::{ResultExt, TryFutureExt};
  45
  46lazy_static! {
  47    static ref GITIGNORE: &'static OsStr = OsStr::new(".gitignore");
  48}
  49
  50#[derive(Clone, Debug)]
  51enum ScanState {
  52    Idle,
  53    Scanning,
  54    Err(Arc<anyhow::Error>),
  55}
  56
  57pub enum Worktree {
  58    Local(LocalWorktree),
  59    Remote(RemoteWorktree),
  60}
  61
  62pub enum Event {
  63    Closed,
  64}
  65
  66pub struct Collaborator {
  67    pub user_id: u64,
  68    pub peer_id: PeerId,
  69    pub replica_id: ReplicaId,
  70}
  71
  72impl Entity for Worktree {
  73    type Event = Event;
  74
  75    fn release(&mut self, cx: &mut MutableAppContext) {
  76        match self {
  77            Self::Local(tree) => {
  78                if let Some(worktree_id) = *tree.remote_id.borrow() {
  79                    let rpc = tree.rpc.clone();
  80                    cx.spawn(|_| async move {
  81                        if let Err(err) = rpc.send(proto::CloseWorktree { worktree_id }).await {
  82                            log::error!("error closing worktree: {}", err);
  83                        }
  84                    })
  85                    .detach();
  86                }
  87            }
  88            Self::Remote(tree) => {
  89                let rpc = tree.client.clone();
  90                let worktree_id = tree.remote_id;
  91                cx.spawn(|_| async move {
  92                    if let Err(err) = rpc.send(proto::LeaveWorktree { worktree_id }).await {
  93                        log::error!("error closing worktree: {}", err);
  94                    }
  95                })
  96                .detach();
  97            }
  98        }
  99    }
 100
 101    fn app_will_quit(
 102        &mut self,
 103        _: &mut MutableAppContext,
 104    ) -> Option<std::pin::Pin<Box<dyn 'static + Future<Output = ()>>>> {
 105        use futures::FutureExt;
 106
 107        if let Self::Local(worktree) = self {
 108            let shutdown_futures = worktree
 109                .language_servers
 110                .drain()
 111                .filter_map(|(_, server)| server.shutdown())
 112                .collect::<Vec<_>>();
 113            Some(
 114                async move {
 115                    futures::future::join_all(shutdown_futures).await;
 116                }
 117                .boxed(),
 118            )
 119        } else {
 120            None
 121        }
 122    }
 123}
 124
 125impl Worktree {
 126    pub async fn open_local(
 127        rpc: Arc<Client>,
 128        path: impl Into<Arc<Path>>,
 129        fs: Arc<dyn Fs>,
 130        languages: Arc<LanguageRegistry>,
 131        cx: &mut AsyncAppContext,
 132    ) -> Result<ModelHandle<Self>> {
 133        let (tree, scan_states_tx) =
 134            LocalWorktree::new(rpc, path, fs.clone(), languages, cx).await?;
 135        tree.update(cx, |tree, cx| {
 136            let tree = tree.as_local_mut().unwrap();
 137            let abs_path = tree.snapshot.abs_path.clone();
 138            let background_snapshot = tree.background_snapshot.clone();
 139            let background = cx.background().clone();
 140            tree._background_scanner_task = Some(cx.background().spawn(async move {
 141                let events = fs.watch(&abs_path, Duration::from_millis(100)).await;
 142                let scanner =
 143                    BackgroundScanner::new(background_snapshot, scan_states_tx, fs, background);
 144                scanner.run(events).await;
 145            }));
 146        });
 147        Ok(tree)
 148    }
 149
 150    pub async fn open_remote(
 151        rpc: Arc<Client>,
 152        id: u64,
 153        languages: Arc<LanguageRegistry>,
 154        cx: &mut AsyncAppContext,
 155    ) -> Result<ModelHandle<Self>> {
 156        let response = rpc.request(proto::JoinWorktree { worktree_id: id }).await?;
 157        Worktree::remote(response, rpc, languages, cx).await
 158    }
 159
 160    async fn remote(
 161        join_response: proto::JoinWorktreeResponse,
 162        rpc: Arc<Client>,
 163        languages: Arc<LanguageRegistry>,
 164        cx: &mut AsyncAppContext,
 165    ) -> Result<ModelHandle<Self>> {
 166        let worktree = join_response
 167            .worktree
 168            .ok_or_else(|| anyhow!("empty worktree"))?;
 169
 170        let remote_id = worktree.id;
 171        let replica_id = join_response.replica_id as ReplicaId;
 172        let peers = join_response.peers;
 173        let root_char_bag: CharBag = worktree
 174            .root_name
 175            .chars()
 176            .map(|c| c.to_ascii_lowercase())
 177            .collect();
 178        let root_name = worktree.root_name.clone();
 179        let (entries_by_path, entries_by_id) = cx
 180            .background()
 181            .spawn(async move {
 182                let mut entries_by_path_edits = Vec::new();
 183                let mut entries_by_id_edits = Vec::new();
 184                for entry in worktree.entries {
 185                    match Entry::try_from((&root_char_bag, entry)) {
 186                        Ok(entry) => {
 187                            entries_by_id_edits.push(Edit::Insert(PathEntry {
 188                                id: entry.id,
 189                                path: entry.path.clone(),
 190                                is_ignored: entry.is_ignored,
 191                                scan_id: 0,
 192                            }));
 193                            entries_by_path_edits.push(Edit::Insert(entry));
 194                        }
 195                        Err(err) => log::warn!("error for remote worktree entry {:?}", err),
 196                    }
 197                }
 198
 199                let mut entries_by_path = SumTree::new();
 200                let mut entries_by_id = SumTree::new();
 201                entries_by_path.edit(entries_by_path_edits, &());
 202                entries_by_id.edit(entries_by_id_edits, &());
 203                (entries_by_path, entries_by_id)
 204            })
 205            .await;
 206
 207        let worktree = cx.update(|cx| {
 208            cx.add_model(|cx: &mut ModelContext<Worktree>| {
 209                let snapshot = Snapshot {
 210                    id: cx.model_id(),
 211                    scan_id: 0,
 212                    abs_path: Path::new("").into(),
 213                    root_name,
 214                    root_char_bag,
 215                    ignores: Default::default(),
 216                    entries_by_path,
 217                    entries_by_id,
 218                    removed_entry_ids: Default::default(),
 219                    next_entry_id: Default::default(),
 220                };
 221
 222                let (updates_tx, mut updates_rx) = postage::mpsc::channel(64);
 223                let (mut snapshot_tx, snapshot_rx) = watch::channel_with(snapshot.clone());
 224
 225                cx.background()
 226                    .spawn(async move {
 227                        while let Some(update) = updates_rx.recv().await {
 228                            let mut snapshot = snapshot_tx.borrow().clone();
 229                            if let Err(error) = snapshot.apply_update(update) {
 230                                log::error!("error applying worktree update: {}", error);
 231                            }
 232                            *snapshot_tx.borrow_mut() = snapshot;
 233                        }
 234                    })
 235                    .detach();
 236
 237                {
 238                    let mut snapshot_rx = snapshot_rx.clone();
 239                    cx.spawn_weak(|this, mut cx| async move {
 240                        while let Some(_) = snapshot_rx.recv().await {
 241                            if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
 242                                this.update(&mut cx, |this, cx| this.poll_snapshot(cx));
 243                            } else {
 244                                break;
 245                            }
 246                        }
 247                    })
 248                    .detach();
 249                }
 250
 251                let _subscriptions = vec![
 252                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_add_peer),
 253                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_remove_peer),
 254                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_update),
 255                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_update_buffer),
 256                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_buffer_saved),
 257                    rpc.subscribe_to_entity(remote_id, cx, Self::handle_unshare),
 258                ];
 259
 260                Worktree::Remote(RemoteWorktree {
 261                    remote_id,
 262                    replica_id,
 263                    snapshot,
 264                    snapshot_rx,
 265                    updates_tx,
 266                    client: rpc.clone(),
 267                    open_buffers: Default::default(),
 268                    collaborators: peers
 269                        .into_iter()
 270                        .map(|p| {
 271                            let peer_id = PeerId(p.peer_id);
 272                            (
 273                                peer_id,
 274                                Collaborator {
 275                                    peer_id,
 276                                    user_id: p.user_id,
 277                                    replica_id: p.replica_id as ReplicaId,
 278                                },
 279                            )
 280                        })
 281                        .collect(),
 282                    queued_operations: Default::default(),
 283                    languages,
 284                    _subscriptions,
 285                })
 286            })
 287        });
 288
 289        Ok(worktree)
 290    }
 291
 292    pub fn as_local(&self) -> Option<&LocalWorktree> {
 293        if let Worktree::Local(worktree) = self {
 294            Some(worktree)
 295        } else {
 296            None
 297        }
 298    }
 299
 300    pub fn as_local_mut(&mut self) -> Option<&mut LocalWorktree> {
 301        if let Worktree::Local(worktree) = self {
 302            Some(worktree)
 303        } else {
 304            None
 305        }
 306    }
 307
 308    pub fn as_remote_mut(&mut self) -> Option<&mut RemoteWorktree> {
 309        if let Worktree::Remote(worktree) = self {
 310            Some(worktree)
 311        } else {
 312            None
 313        }
 314    }
 315
 316    pub fn snapshot(&self) -> Snapshot {
 317        match self {
 318            Worktree::Local(worktree) => worktree.snapshot(),
 319            Worktree::Remote(worktree) => worktree.snapshot(),
 320        }
 321    }
 322
 323    pub fn replica_id(&self) -> ReplicaId {
 324        match self {
 325            Worktree::Local(_) => 0,
 326            Worktree::Remote(worktree) => worktree.replica_id,
 327        }
 328    }
 329
 330    pub fn languages(&self) -> &Arc<LanguageRegistry> {
 331        match self {
 332            Worktree::Local(worktree) => &worktree.languages,
 333            Worktree::Remote(worktree) => &worktree.languages,
 334        }
 335    }
 336
 337    pub fn handle_add_peer(
 338        &mut self,
 339        envelope: TypedEnvelope<proto::AddPeer>,
 340        _: Arc<Client>,
 341        cx: &mut ModelContext<Self>,
 342    ) -> Result<()> {
 343        match self {
 344            Worktree::Local(worktree) => worktree.add_peer(envelope, cx),
 345            Worktree::Remote(worktree) => worktree.add_peer(envelope, cx),
 346        }
 347    }
 348
 349    pub fn handle_remove_peer(
 350        &mut self,
 351        envelope: TypedEnvelope<proto::RemovePeer>,
 352        _: Arc<Client>,
 353        cx: &mut ModelContext<Self>,
 354    ) -> Result<()> {
 355        match self {
 356            Worktree::Local(worktree) => worktree.remove_peer(envelope, cx),
 357            Worktree::Remote(worktree) => worktree.remove_peer(envelope, cx),
 358        }
 359    }
 360
 361    pub fn handle_update(
 362        &mut self,
 363        envelope: TypedEnvelope<proto::UpdateWorktree>,
 364        _: Arc<Client>,
 365        cx: &mut ModelContext<Self>,
 366    ) -> anyhow::Result<()> {
 367        self.as_remote_mut()
 368            .unwrap()
 369            .update_from_remote(envelope, cx)
 370    }
 371
 372    pub fn handle_open_buffer(
 373        &mut self,
 374        envelope: TypedEnvelope<proto::OpenBuffer>,
 375        rpc: Arc<Client>,
 376        cx: &mut ModelContext<Self>,
 377    ) -> anyhow::Result<()> {
 378        let receipt = envelope.receipt();
 379
 380        let response = self
 381            .as_local_mut()
 382            .unwrap()
 383            .open_remote_buffer(envelope, cx);
 384
 385        cx.background()
 386            .spawn(
 387                async move {
 388                    rpc.respond(receipt, response.await?).await?;
 389                    Ok(())
 390                }
 391                .log_err(),
 392            )
 393            .detach();
 394
 395        Ok(())
 396    }
 397
 398    pub fn handle_close_buffer(
 399        &mut self,
 400        envelope: TypedEnvelope<proto::CloseBuffer>,
 401        _: Arc<Client>,
 402        cx: &mut ModelContext<Self>,
 403    ) -> anyhow::Result<()> {
 404        self.as_local_mut()
 405            .unwrap()
 406            .close_remote_buffer(envelope, cx)
 407    }
 408
 409    pub fn collaborators(&self) -> &HashMap<PeerId, Collaborator> {
 410        match self {
 411            Worktree::Local(worktree) => &worktree.collaborators,
 412            Worktree::Remote(worktree) => &worktree.collaborators,
 413        }
 414    }
 415
 416    pub fn open_buffer(
 417        &mut self,
 418        path: impl AsRef<Path>,
 419        cx: &mut ModelContext<Self>,
 420    ) -> Task<Result<ModelHandle<Buffer>>> {
 421        match self {
 422            Worktree::Local(worktree) => worktree.open_buffer(path.as_ref(), cx),
 423            Worktree::Remote(worktree) => worktree.open_buffer(path.as_ref(), cx),
 424        }
 425    }
 426
 427    #[cfg(feature = "test-support")]
 428    pub fn has_open_buffer(&self, path: impl AsRef<Path>, cx: &AppContext) -> bool {
 429        let mut open_buffers: Box<dyn Iterator<Item = _>> = match self {
 430            Worktree::Local(worktree) => Box::new(worktree.open_buffers.values()),
 431            Worktree::Remote(worktree) => {
 432                Box::new(worktree.open_buffers.values().filter_map(|buf| {
 433                    if let RemoteBuffer::Loaded(buf) = buf {
 434                        Some(buf)
 435                    } else {
 436                        None
 437                    }
 438                }))
 439            }
 440        };
 441
 442        let path = path.as_ref();
 443        open_buffers
 444            .find(|buffer| {
 445                if let Some(file) = buffer.upgrade(cx).and_then(|buffer| buffer.read(cx).file()) {
 446                    file.path().as_ref() == path
 447                } else {
 448                    false
 449                }
 450            })
 451            .is_some()
 452    }
 453
 454    pub fn handle_update_buffer(
 455        &mut self,
 456        envelope: TypedEnvelope<proto::UpdateBuffer>,
 457        _: Arc<Client>,
 458        cx: &mut ModelContext<Self>,
 459    ) -> Result<()> {
 460        let payload = envelope.payload.clone();
 461        let buffer_id = payload.buffer_id as usize;
 462        let ops = payload
 463            .operations
 464            .into_iter()
 465            .map(|op| language::proto::deserialize_operation(op))
 466            .collect::<Result<Vec<_>, _>>()?;
 467
 468        match self {
 469            Worktree::Local(worktree) => {
 470                let buffer = worktree
 471                    .open_buffers
 472                    .get(&buffer_id)
 473                    .and_then(|buf| buf.upgrade(cx))
 474                    .ok_or_else(|| {
 475                        anyhow!("invalid buffer {} in update buffer message", buffer_id)
 476                    })?;
 477                buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
 478            }
 479            Worktree::Remote(worktree) => match worktree.open_buffers.get_mut(&buffer_id) {
 480                Some(RemoteBuffer::Operations(pending_ops)) => pending_ops.extend(ops),
 481                Some(RemoteBuffer::Loaded(buffer)) => {
 482                    if let Some(buffer) = buffer.upgrade(cx) {
 483                        buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))?;
 484                    } else {
 485                        worktree
 486                            .open_buffers
 487                            .insert(buffer_id, RemoteBuffer::Operations(ops));
 488                    }
 489                }
 490                None => {
 491                    worktree
 492                        .open_buffers
 493                        .insert(buffer_id, RemoteBuffer::Operations(ops));
 494                }
 495            },
 496        }
 497
 498        Ok(())
 499    }
 500
 501    pub fn handle_save_buffer(
 502        &mut self,
 503        envelope: TypedEnvelope<proto::SaveBuffer>,
 504        rpc: Arc<Client>,
 505        cx: &mut ModelContext<Self>,
 506    ) -> Result<()> {
 507        let sender_id = envelope.original_sender_id()?;
 508        let buffer = self
 509            .as_local()
 510            .unwrap()
 511            .shared_buffers
 512            .get(&sender_id)
 513            .and_then(|shared_buffers| shared_buffers.get(&envelope.payload.buffer_id).cloned())
 514            .ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
 515
 516        let receipt = envelope.receipt();
 517        let worktree_id = envelope.payload.worktree_id;
 518        let buffer_id = envelope.payload.buffer_id;
 519        let save = cx.spawn(|_, mut cx| async move {
 520            buffer.update(&mut cx, |buffer, cx| buffer.save(cx))?.await
 521        });
 522
 523        cx.background()
 524            .spawn(
 525                async move {
 526                    let (version, mtime) = save.await?;
 527
 528                    rpc.respond(
 529                        receipt,
 530                        proto::BufferSaved {
 531                            worktree_id,
 532                            buffer_id,
 533                            version: (&version).into(),
 534                            mtime: Some(mtime.into()),
 535                        },
 536                    )
 537                    .await?;
 538
 539                    Ok(())
 540                }
 541                .log_err(),
 542            )
 543            .detach();
 544
 545        Ok(())
 546    }
 547
 548    pub fn handle_buffer_saved(
 549        &mut self,
 550        envelope: TypedEnvelope<proto::BufferSaved>,
 551        _: Arc<Client>,
 552        cx: &mut ModelContext<Self>,
 553    ) -> Result<()> {
 554        let payload = envelope.payload.clone();
 555        let worktree = self.as_remote_mut().unwrap();
 556        if let Some(buffer) = worktree
 557            .open_buffers
 558            .get(&(payload.buffer_id as usize))
 559            .and_then(|buf| buf.upgrade(cx))
 560        {
 561            buffer.update(cx, |buffer, cx| {
 562                let version = payload.version.try_into()?;
 563                let mtime = payload
 564                    .mtime
 565                    .ok_or_else(|| anyhow!("missing mtime"))?
 566                    .into();
 567                buffer.did_save(version, mtime, None, cx);
 568                Result::<_, anyhow::Error>::Ok(())
 569            })?;
 570        }
 571        Ok(())
 572    }
 573
 574    pub fn handle_unshare(
 575        &mut self,
 576        _: TypedEnvelope<proto::UnshareWorktree>,
 577        _: Arc<Client>,
 578        cx: &mut ModelContext<Self>,
 579    ) -> Result<()> {
 580        cx.emit(Event::Closed);
 581        Ok(())
 582    }
 583
 584    fn poll_snapshot(&mut self, cx: &mut ModelContext<Self>) {
 585        match self {
 586            Self::Local(worktree) => {
 587                let is_fake_fs = worktree.fs.is_fake();
 588                worktree.snapshot = worktree.background_snapshot.lock().clone();
 589                if worktree.is_scanning() {
 590                    if worktree.poll_task.is_none() {
 591                        worktree.poll_task = Some(cx.spawn(|this, mut cx| async move {
 592                            if is_fake_fs {
 593                                smol::future::yield_now().await;
 594                            } else {
 595                                smol::Timer::after(Duration::from_millis(100)).await;
 596                            }
 597                            this.update(&mut cx, |this, cx| {
 598                                this.as_local_mut().unwrap().poll_task = None;
 599                                this.poll_snapshot(cx);
 600                            })
 601                        }));
 602                    }
 603                } else {
 604                    worktree.poll_task.take();
 605                    self.update_open_buffers(cx);
 606                }
 607            }
 608            Self::Remote(worktree) => {
 609                worktree.snapshot = worktree.snapshot_rx.borrow().clone();
 610                self.update_open_buffers(cx);
 611            }
 612        };
 613
 614        cx.notify();
 615    }
 616
 617    fn update_open_buffers(&mut self, cx: &mut ModelContext<Self>) {
 618        let open_buffers: Box<dyn Iterator<Item = _>> = match &self {
 619            Self::Local(worktree) => Box::new(worktree.open_buffers.iter()),
 620            Self::Remote(worktree) => {
 621                Box::new(worktree.open_buffers.iter().filter_map(|(id, buf)| {
 622                    if let RemoteBuffer::Loaded(buf) = buf {
 623                        Some((id, buf))
 624                    } else {
 625                        None
 626                    }
 627                }))
 628            }
 629        };
 630
 631        let local = self.as_local().is_some();
 632        let worktree_path = self.abs_path.clone();
 633        let worktree_handle = cx.handle();
 634        let mut buffers_to_delete = Vec::new();
 635        for (buffer_id, buffer) in open_buffers {
 636            if let Some(buffer) = buffer.upgrade(cx) {
 637                buffer.update(cx, |buffer, cx| {
 638                    if let Some(old_file) = buffer.file() {
 639                        let new_file = if let Some(entry) = old_file
 640                            .entry_id()
 641                            .and_then(|entry_id| self.entry_for_id(entry_id))
 642                        {
 643                            File {
 644                                is_local: local,
 645                                worktree_path: worktree_path.clone(),
 646                                entry_id: Some(entry.id),
 647                                mtime: entry.mtime,
 648                                path: entry.path.clone(),
 649                                worktree: worktree_handle.clone(),
 650                            }
 651                        } else if let Some(entry) = self.entry_for_path(old_file.path().as_ref()) {
 652                            File {
 653                                is_local: local,
 654                                worktree_path: worktree_path.clone(),
 655                                entry_id: Some(entry.id),
 656                                mtime: entry.mtime,
 657                                path: entry.path.clone(),
 658                                worktree: worktree_handle.clone(),
 659                            }
 660                        } else {
 661                            File {
 662                                is_local: local,
 663                                worktree_path: worktree_path.clone(),
 664                                entry_id: None,
 665                                path: old_file.path().clone(),
 666                                mtime: old_file.mtime(),
 667                                worktree: worktree_handle.clone(),
 668                            }
 669                        };
 670
 671                        if let Some(task) = buffer.file_updated(Box::new(new_file), cx) {
 672                            task.detach();
 673                        }
 674                    }
 675                });
 676            } else {
 677                buffers_to_delete.push(*buffer_id);
 678            }
 679        }
 680
 681        for buffer_id in buffers_to_delete {
 682            match self {
 683                Self::Local(worktree) => {
 684                    worktree.open_buffers.remove(&buffer_id);
 685                }
 686                Self::Remote(worktree) => {
 687                    worktree.open_buffers.remove(&buffer_id);
 688                }
 689            }
 690        }
 691    }
 692
 693    fn update_diagnostics(
 694        &mut self,
 695        params: lsp::PublishDiagnosticsParams,
 696        cx: &mut ModelContext<Worktree>,
 697    ) -> Result<()> {
 698        let this = self.as_local_mut().ok_or_else(|| anyhow!("not local"))?;
 699        let file_path = params
 700            .uri
 701            .to_file_path()
 702            .map_err(|_| anyhow!("URI is not a file"))?
 703            .strip_prefix(&this.abs_path)
 704            .context("path is not within worktree")?
 705            .to_owned();
 706
 707        for buffer in this.open_buffers.values() {
 708            if let Some(buffer) = buffer.upgrade(cx) {
 709                if buffer
 710                    .read(cx)
 711                    .file()
 712                    .map_or(false, |file| file.path().as_ref() == file_path)
 713                {
 714                    let (remote_id, operation) = buffer.update(cx, |buffer, cx| {
 715                        (
 716                            buffer.remote_id(),
 717                            buffer.update_diagnostics(params.version, params.diagnostics, cx),
 718                        )
 719                    });
 720                    self.send_buffer_update(remote_id, operation?, cx);
 721                    return Ok(());
 722                }
 723            }
 724        }
 725
 726        this.diagnostics.insert(file_path, params.diagnostics);
 727        Ok(())
 728    }
 729
 730    fn send_buffer_update(
 731        &mut self,
 732        buffer_id: u64,
 733        operation: Operation,
 734        cx: &mut ModelContext<Self>,
 735    ) {
 736        if let Some((rpc, remote_id)) = match self {
 737            Worktree::Local(worktree) => worktree
 738                .remote_id
 739                .borrow()
 740                .map(|id| (worktree.rpc.clone(), id)),
 741            Worktree::Remote(worktree) => Some((worktree.client.clone(), worktree.remote_id)),
 742        } {
 743            cx.spawn(|worktree, mut cx| async move {
 744                if let Err(error) = rpc
 745                    .request(proto::UpdateBuffer {
 746                        worktree_id: remote_id,
 747                        buffer_id,
 748                        operations: vec![language::proto::serialize_operation(&operation)],
 749                    })
 750                    .await
 751                {
 752                    worktree.update(&mut cx, |worktree, _| {
 753                        log::error!("error sending buffer operation: {}", error);
 754                        match worktree {
 755                            Worktree::Local(t) => &mut t.queued_operations,
 756                            Worktree::Remote(t) => &mut t.queued_operations,
 757                        }
 758                        .push((buffer_id, operation));
 759                    });
 760                }
 761            })
 762            .detach();
 763        }
 764    }
 765}
 766
 767impl Deref for Worktree {
 768    type Target = Snapshot;
 769
 770    fn deref(&self) -> &Self::Target {
 771        match self {
 772            Worktree::Local(worktree) => &worktree.snapshot,
 773            Worktree::Remote(worktree) => &worktree.snapshot,
 774        }
 775    }
 776}
 777
 778pub struct LocalWorktree {
 779    snapshot: Snapshot,
 780    config: WorktreeConfig,
 781    background_snapshot: Arc<Mutex<Snapshot>>,
 782    last_scan_state_rx: watch::Receiver<ScanState>,
 783    _background_scanner_task: Option<Task<()>>,
 784    _maintain_remote_id_task: Task<Option<()>>,
 785    poll_task: Option<Task<()>>,
 786    remote_id: watch::Receiver<Option<u64>>,
 787    share: Option<ShareState>,
 788    open_buffers: HashMap<usize, WeakModelHandle<Buffer>>,
 789    shared_buffers: HashMap<PeerId, HashMap<u64, ModelHandle<Buffer>>>,
 790    diagnostics: HashMap<PathBuf, Vec<lsp::Diagnostic>>,
 791    collaborators: HashMap<PeerId, Collaborator>,
 792    queued_operations: Vec<(u64, Operation)>,
 793    languages: Arc<LanguageRegistry>,
 794    rpc: Arc<Client>,
 795    fs: Arc<dyn Fs>,
 796    language_servers: HashMap<String, Arc<LanguageServer>>,
 797}
 798
 799#[derive(Default, Deserialize)]
 800struct WorktreeConfig {
 801    collaborators: Vec<String>,
 802}
 803
 804impl LocalWorktree {
 805    async fn new(
 806        rpc: Arc<Client>,
 807        path: impl Into<Arc<Path>>,
 808        fs: Arc<dyn Fs>,
 809        languages: Arc<LanguageRegistry>,
 810        cx: &mut AsyncAppContext,
 811    ) -> Result<(ModelHandle<Worktree>, Sender<ScanState>)> {
 812        let abs_path = path.into();
 813        let path: Arc<Path> = Arc::from(Path::new(""));
 814        let next_entry_id = AtomicUsize::new(0);
 815
 816        // After determining whether the root entry is a file or a directory, populate the
 817        // snapshot's "root name", which will be used for the purpose of fuzzy matching.
 818        let root_name = abs_path
 819            .file_name()
 820            .map_or(String::new(), |f| f.to_string_lossy().to_string());
 821        let root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect();
 822        let metadata = fs.metadata(&abs_path).await?;
 823
 824        let mut config = WorktreeConfig::default();
 825        if let Ok(zed_toml) = fs.load(&abs_path.join(".zed.toml")).await {
 826            if let Ok(parsed) = toml::from_str(&zed_toml) {
 827                config = parsed;
 828            }
 829        }
 830
 831        let (scan_states_tx, scan_states_rx) = smol::channel::unbounded();
 832        let (mut last_scan_state_tx, last_scan_state_rx) = watch::channel_with(ScanState::Scanning);
 833        let tree = cx.add_model(move |cx: &mut ModelContext<Worktree>| {
 834            let mut snapshot = Snapshot {
 835                id: cx.model_id(),
 836                scan_id: 0,
 837                abs_path,
 838                root_name: root_name.clone(),
 839                root_char_bag,
 840                ignores: Default::default(),
 841                entries_by_path: Default::default(),
 842                entries_by_id: Default::default(),
 843                removed_entry_ids: Default::default(),
 844                next_entry_id: Arc::new(next_entry_id),
 845            };
 846            if let Some(metadata) = metadata {
 847                snapshot.insert_entry(
 848                    Entry::new(
 849                        path.into(),
 850                        &metadata,
 851                        &snapshot.next_entry_id,
 852                        snapshot.root_char_bag,
 853                    ),
 854                    fs.as_ref(),
 855                );
 856            }
 857
 858            let (mut remote_id_tx, remote_id_rx) = watch::channel();
 859            let _maintain_remote_id_task = cx.spawn_weak({
 860                let rpc = rpc.clone();
 861                move |this, cx| {
 862                    async move {
 863                        let mut status = rpc.status();
 864                        while let Some(status) = status.recv().await {
 865                            if let Some(this) = this.upgrade(&cx) {
 866                                let remote_id = if let client::Status::Connected { .. } = status {
 867                                    let authorized_logins = this.read_with(&cx, |this, _| {
 868                                        this.as_local().unwrap().config.collaborators.clone()
 869                                    });
 870                                    let response = rpc
 871                                        .request(proto::OpenWorktree {
 872                                            root_name: root_name.clone(),
 873                                            authorized_logins,
 874                                        })
 875                                        .await?;
 876
 877                                    Some(response.worktree_id)
 878                                } else {
 879                                    None
 880                                };
 881                                if remote_id_tx.send(remote_id).await.is_err() {
 882                                    break;
 883                                }
 884                            }
 885                        }
 886                        Ok(())
 887                    }
 888                    .log_err()
 889                }
 890            });
 891
 892            let tree = Self {
 893                snapshot: snapshot.clone(),
 894                config,
 895                remote_id: remote_id_rx,
 896                background_snapshot: Arc::new(Mutex::new(snapshot)),
 897                last_scan_state_rx,
 898                _background_scanner_task: None,
 899                _maintain_remote_id_task,
 900                share: None,
 901                poll_task: None,
 902                open_buffers: Default::default(),
 903                shared_buffers: Default::default(),
 904                diagnostics: Default::default(),
 905                queued_operations: Default::default(),
 906                collaborators: Default::default(),
 907                languages,
 908                rpc,
 909                fs,
 910                language_servers: Default::default(),
 911            };
 912
 913            cx.spawn_weak(|this, mut cx| async move {
 914                while let Ok(scan_state) = scan_states_rx.recv().await {
 915                    if let Some(handle) = cx.read(|cx| this.upgrade(cx)) {
 916                        let to_send = handle.update(&mut cx, |this, cx| {
 917                            last_scan_state_tx.blocking_send(scan_state).ok();
 918                            this.poll_snapshot(cx);
 919                            let tree = this.as_local_mut().unwrap();
 920                            if !tree.is_scanning() {
 921                                if let Some(share) = tree.share.as_ref() {
 922                                    return Some((tree.snapshot(), share.snapshots_tx.clone()));
 923                                }
 924                            }
 925                            None
 926                        });
 927
 928                        if let Some((snapshot, snapshots_to_send_tx)) = to_send {
 929                            if let Err(err) = snapshots_to_send_tx.send(snapshot).await {
 930                                log::error!("error submitting snapshot to send {}", err);
 931                            }
 932                        }
 933                    } else {
 934                        break;
 935                    }
 936                }
 937            })
 938            .detach();
 939
 940            Worktree::Local(tree)
 941        });
 942
 943        Ok((tree, scan_states_tx))
 944    }
 945
 946    pub fn languages(&self) -> &LanguageRegistry {
 947        &self.languages
 948    }
 949
 950    pub fn ensure_language_server(
 951        &mut self,
 952        language: &Language,
 953        cx: &mut ModelContext<Worktree>,
 954    ) -> Option<Arc<LanguageServer>> {
 955        if let Some(server) = self.language_servers.get(language.name()) {
 956            return Some(server.clone());
 957        }
 958
 959        if let Some(language_server) = language
 960            .start_server(self.abs_path(), cx)
 961            .log_err()
 962            .flatten()
 963        {
 964            let (diagnostics_tx, diagnostics_rx) = smol::channel::unbounded();
 965            language_server
 966                .on_notification::<lsp::notification::PublishDiagnostics, _>(move |params| {
 967                    smol::block_on(diagnostics_tx.send(params)).ok();
 968                })
 969                .detach();
 970            cx.spawn_weak(|this, mut cx| async move {
 971                while let Ok(diagnostics) = diagnostics_rx.recv().await {
 972                    if let Some(handle) = cx.read(|cx| this.upgrade(cx)) {
 973                        handle.update(&mut cx, |this, cx| {
 974                            this.update_diagnostics(diagnostics, cx).log_err();
 975                        });
 976                    } else {
 977                        break;
 978                    }
 979                }
 980            })
 981            .detach();
 982
 983            self.language_servers
 984                .insert(language.name().to_string(), language_server.clone());
 985            Some(language_server.clone())
 986        } else {
 987            None
 988        }
 989    }
 990
 991    pub fn open_buffer(
 992        &mut self,
 993        path: &Path,
 994        cx: &mut ModelContext<Worktree>,
 995    ) -> Task<Result<ModelHandle<Buffer>>> {
 996        let handle = cx.handle();
 997
 998        // If there is already a buffer for the given path, then return it.
 999        let mut existing_buffer = None;
1000        self.open_buffers.retain(|_buffer_id, buffer| {
1001            if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
1002                if let Some(file) = buffer.read(cx.as_ref()).file() {
1003                    if file.worktree_id() == handle.id() && file.path().as_ref() == path {
1004                        existing_buffer = Some(buffer);
1005                    }
1006                }
1007                true
1008            } else {
1009                false
1010            }
1011        });
1012
1013        let path = Arc::from(path);
1014        cx.spawn(|this, mut cx| async move {
1015            if let Some(existing_buffer) = existing_buffer {
1016                Ok(existing_buffer)
1017            } else {
1018                let (file, contents) = this
1019                    .update(&mut cx, |this, cx| this.as_local().unwrap().load(&path, cx))
1020                    .await?;
1021                let language = this.read_with(&cx, |this, _| {
1022                    use language::File;
1023                    this.languages().select_language(file.full_path()).cloned()
1024                });
1025                let (diagnostics, language_server) = this.update(&mut cx, |this, cx| {
1026                    let this = this.as_local_mut().unwrap();
1027                    (
1028                        this.diagnostics.remove(path.as_ref()),
1029                        language
1030                            .as_ref()
1031                            .and_then(|language| this.ensure_language_server(language, cx)),
1032                    )
1033                });
1034                let buffer = cx.add_model(|cx| {
1035                    let mut buffer = Buffer::from_file(0, contents, Box::new(file), cx);
1036                    buffer.set_language(language, language_server, cx);
1037                    if let Some(diagnostics) = diagnostics {
1038                        buffer.update_diagnostics(None, diagnostics, cx).unwrap();
1039                    }
1040                    buffer
1041                });
1042                this.update(&mut cx, |this, _| {
1043                    let this = this
1044                        .as_local_mut()
1045                        .ok_or_else(|| anyhow!("must be a local worktree"))?;
1046
1047                    this.open_buffers.insert(buffer.id(), buffer.downgrade());
1048                    Ok(buffer)
1049                })
1050            }
1051        })
1052    }
1053
1054    pub fn open_remote_buffer(
1055        &mut self,
1056        envelope: TypedEnvelope<proto::OpenBuffer>,
1057        cx: &mut ModelContext<Worktree>,
1058    ) -> Task<Result<proto::OpenBufferResponse>> {
1059        let peer_id = envelope.original_sender_id();
1060        let path = Path::new(&envelope.payload.path);
1061
1062        let buffer = self.open_buffer(path, cx);
1063
1064        cx.spawn(|this, mut cx| async move {
1065            let buffer = buffer.await?;
1066            this.update(&mut cx, |this, cx| {
1067                this.as_local_mut()
1068                    .unwrap()
1069                    .shared_buffers
1070                    .entry(peer_id?)
1071                    .or_default()
1072                    .insert(buffer.id() as u64, buffer.clone());
1073
1074                Ok(proto::OpenBufferResponse {
1075                    buffer: Some(buffer.update(cx.as_mut(), |buffer, _| buffer.to_proto())),
1076                })
1077            })
1078        })
1079    }
1080
1081    pub fn close_remote_buffer(
1082        &mut self,
1083        envelope: TypedEnvelope<proto::CloseBuffer>,
1084        cx: &mut ModelContext<Worktree>,
1085    ) -> Result<()> {
1086        if let Some(shared_buffers) = self.shared_buffers.get_mut(&envelope.original_sender_id()?) {
1087            shared_buffers.remove(&envelope.payload.buffer_id);
1088            cx.notify();
1089        }
1090
1091        Ok(())
1092    }
1093
1094    pub fn add_peer(
1095        &mut self,
1096        envelope: TypedEnvelope<proto::AddPeer>,
1097        cx: &mut ModelContext<Worktree>,
1098    ) -> Result<()> {
1099        let peer = envelope
1100            .payload
1101            .peer
1102            .as_ref()
1103            .ok_or_else(|| anyhow!("empty peer"))?;
1104        let peer_id = PeerId(peer.peer_id);
1105        self.collaborators.insert(
1106            peer_id,
1107            Collaborator {
1108                peer_id,
1109                user_id: peer.user_id,
1110                replica_id: peer.replica_id as ReplicaId,
1111            },
1112        );
1113        cx.notify();
1114
1115        Ok(())
1116    }
1117
1118    pub fn remove_peer(
1119        &mut self,
1120        envelope: TypedEnvelope<proto::RemovePeer>,
1121        cx: &mut ModelContext<Worktree>,
1122    ) -> Result<()> {
1123        let peer_id = PeerId(envelope.payload.peer_id);
1124        let replica_id = self
1125            .collaborators
1126            .remove(&peer_id)
1127            .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
1128            .replica_id;
1129        self.shared_buffers.remove(&peer_id);
1130        for (_, buffer) in &self.open_buffers {
1131            if let Some(buffer) = buffer.upgrade(cx) {
1132                buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
1133            }
1134        }
1135        cx.notify();
1136
1137        Ok(())
1138    }
1139
1140    pub fn scan_complete(&self) -> impl Future<Output = ()> {
1141        let mut scan_state_rx = self.last_scan_state_rx.clone();
1142        async move {
1143            let mut scan_state = Some(scan_state_rx.borrow().clone());
1144            while let Some(ScanState::Scanning) = scan_state {
1145                scan_state = scan_state_rx.recv().await;
1146            }
1147        }
1148    }
1149
1150    pub fn remote_id(&self) -> Option<u64> {
1151        *self.remote_id.borrow()
1152    }
1153
1154    pub fn next_remote_id(&self) -> impl Future<Output = Option<u64>> {
1155        let mut remote_id = self.remote_id.clone();
1156        async move {
1157            while let Some(remote_id) = remote_id.recv().await {
1158                if remote_id.is_some() {
1159                    return remote_id;
1160                }
1161            }
1162            None
1163        }
1164    }
1165
1166    fn is_scanning(&self) -> bool {
1167        if let ScanState::Scanning = *self.last_scan_state_rx.borrow() {
1168            true
1169        } else {
1170            false
1171        }
1172    }
1173
1174    pub fn snapshot(&self) -> Snapshot {
1175        self.snapshot.clone()
1176    }
1177
1178    pub fn abs_path(&self) -> &Path {
1179        self.snapshot.abs_path.as_ref()
1180    }
1181
1182    pub fn contains_abs_path(&self, path: &Path) -> bool {
1183        path.starts_with(&self.snapshot.abs_path)
1184    }
1185
1186    fn absolutize(&self, path: &Path) -> PathBuf {
1187        if path.file_name().is_some() {
1188            self.snapshot.abs_path.join(path)
1189        } else {
1190            self.snapshot.abs_path.to_path_buf()
1191        }
1192    }
1193
1194    fn load(&self, path: &Path, cx: &mut ModelContext<Worktree>) -> Task<Result<(File, String)>> {
1195        let handle = cx.handle();
1196        let path = Arc::from(path);
1197        let worktree_path = self.abs_path.clone();
1198        let abs_path = self.absolutize(&path);
1199        let background_snapshot = self.background_snapshot.clone();
1200        let fs = self.fs.clone();
1201        cx.spawn(|this, mut cx| async move {
1202            let text = fs.load(&abs_path).await?;
1203            // Eagerly populate the snapshot with an updated entry for the loaded file
1204            let entry = refresh_entry(fs.as_ref(), &background_snapshot, path, &abs_path).await?;
1205            this.update(&mut cx, |this, cx| this.poll_snapshot(cx));
1206            Ok((
1207                File {
1208                    entry_id: Some(entry.id),
1209                    worktree: handle,
1210                    worktree_path,
1211                    path: entry.path,
1212                    mtime: entry.mtime,
1213                    is_local: true,
1214                },
1215                text,
1216            ))
1217        })
1218    }
1219
1220    pub fn save_buffer_as(
1221        &self,
1222        buffer: ModelHandle<Buffer>,
1223        path: impl Into<Arc<Path>>,
1224        text: Rope,
1225        cx: &mut ModelContext<Worktree>,
1226    ) -> Task<Result<File>> {
1227        let save = self.save(path, text, cx);
1228        cx.spawn(|this, mut cx| async move {
1229            let entry = save.await?;
1230            this.update(&mut cx, |this, cx| {
1231                let this = this.as_local_mut().unwrap();
1232                this.open_buffers.insert(buffer.id(), buffer.downgrade());
1233                Ok(File {
1234                    entry_id: Some(entry.id),
1235                    worktree: cx.handle(),
1236                    worktree_path: this.abs_path.clone(),
1237                    path: entry.path,
1238                    mtime: entry.mtime,
1239                    is_local: true,
1240                })
1241            })
1242        })
1243    }
1244
1245    fn save(
1246        &self,
1247        path: impl Into<Arc<Path>>,
1248        text: Rope,
1249        cx: &mut ModelContext<Worktree>,
1250    ) -> Task<Result<Entry>> {
1251        let path = path.into();
1252        let abs_path = self.absolutize(&path);
1253        let background_snapshot = self.background_snapshot.clone();
1254        let fs = self.fs.clone();
1255        let save = cx.background().spawn(async move {
1256            fs.save(&abs_path, &text).await?;
1257            refresh_entry(fs.as_ref(), &background_snapshot, path.clone(), &abs_path).await
1258        });
1259
1260        cx.spawn(|this, mut cx| async move {
1261            let entry = save.await?;
1262            this.update(&mut cx, |this, cx| this.poll_snapshot(cx));
1263            Ok(entry)
1264        })
1265    }
1266
1267    pub fn share(&mut self, cx: &mut ModelContext<Worktree>) -> Task<anyhow::Result<u64>> {
1268        let snapshot = self.snapshot();
1269        let share_request = self.share_request(cx);
1270        let rpc = self.rpc.clone();
1271        cx.spawn(|this, mut cx| async move {
1272            let share_request = if let Some(request) = share_request.await {
1273                request
1274            } else {
1275                return Err(anyhow!("failed to open worktree on the server"));
1276            };
1277
1278            let remote_id = share_request.worktree.as_ref().unwrap().id;
1279            let share_response = rpc.request(share_request).await?;
1280
1281            log::info!("sharing worktree {:?}", share_response);
1282            let (snapshots_to_send_tx, snapshots_to_send_rx) =
1283                smol::channel::unbounded::<Snapshot>();
1284
1285            cx.background()
1286                .spawn({
1287                    let rpc = rpc.clone();
1288                    async move {
1289                        let mut prev_snapshot = snapshot;
1290                        while let Ok(snapshot) = snapshots_to_send_rx.recv().await {
1291                            let message = snapshot.build_update(&prev_snapshot, remote_id, false);
1292                            match rpc.send(message).await {
1293                                Ok(()) => prev_snapshot = snapshot,
1294                                Err(err) => log::error!("error sending snapshot diff {}", err),
1295                            }
1296                        }
1297                    }
1298                })
1299                .detach();
1300
1301            this.update(&mut cx, |worktree, cx| {
1302                let _subscriptions = vec![
1303                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_add_peer),
1304                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_remove_peer),
1305                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_open_buffer),
1306                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_close_buffer),
1307                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_update_buffer),
1308                    rpc.subscribe_to_entity(remote_id, cx, Worktree::handle_save_buffer),
1309                ];
1310
1311                let worktree = worktree.as_local_mut().unwrap();
1312                worktree.share = Some(ShareState {
1313                    snapshots_tx: snapshots_to_send_tx,
1314                    _subscriptions,
1315                });
1316            });
1317
1318            Ok(remote_id)
1319        })
1320    }
1321
1322    pub fn unshare(&mut self, cx: &mut ModelContext<Worktree>) {
1323        self.share.take();
1324        let rpc = self.rpc.clone();
1325        let remote_id = self.remote_id();
1326        cx.foreground()
1327            .spawn(
1328                async move {
1329                    if let Some(worktree_id) = remote_id {
1330                        rpc.send(proto::UnshareWorktree { worktree_id }).await?;
1331                    }
1332                    Ok(())
1333                }
1334                .log_err(),
1335            )
1336            .detach()
1337    }
1338
1339    fn share_request(&self, cx: &mut ModelContext<Worktree>) -> Task<Option<proto::ShareWorktree>> {
1340        let remote_id = self.next_remote_id();
1341        let snapshot = self.snapshot();
1342        let root_name = self.root_name.clone();
1343        cx.background().spawn(async move {
1344            remote_id.await.map(|id| {
1345                let entries = snapshot
1346                    .entries_by_path
1347                    .cursor::<()>()
1348                    .filter(|e| !e.is_ignored)
1349                    .map(Into::into)
1350                    .collect();
1351                proto::ShareWorktree {
1352                    worktree: Some(proto::Worktree {
1353                        id,
1354                        root_name,
1355                        entries,
1356                    }),
1357                }
1358            })
1359        })
1360    }
1361}
1362
1363fn build_gitignore(abs_path: &Path, fs: &dyn Fs) -> Result<Gitignore> {
1364    let contents = smol::block_on(fs.load(&abs_path))?;
1365    let parent = abs_path.parent().unwrap_or(Path::new("/"));
1366    let mut builder = GitignoreBuilder::new(parent);
1367    for line in contents.lines() {
1368        builder.add_line(Some(abs_path.into()), line)?;
1369    }
1370    Ok(builder.build()?)
1371}
1372
1373impl Deref for LocalWorktree {
1374    type Target = Snapshot;
1375
1376    fn deref(&self) -> &Self::Target {
1377        &self.snapshot
1378    }
1379}
1380
1381impl fmt::Debug for LocalWorktree {
1382    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1383        self.snapshot.fmt(f)
1384    }
1385}
1386
1387struct ShareState {
1388    snapshots_tx: Sender<Snapshot>,
1389    _subscriptions: Vec<client::Subscription>,
1390}
1391
1392pub struct RemoteWorktree {
1393    remote_id: u64,
1394    snapshot: Snapshot,
1395    snapshot_rx: watch::Receiver<Snapshot>,
1396    client: Arc<Client>,
1397    updates_tx: postage::mpsc::Sender<proto::UpdateWorktree>,
1398    replica_id: ReplicaId,
1399    open_buffers: HashMap<usize, RemoteBuffer>,
1400    collaborators: HashMap<PeerId, Collaborator>,
1401    languages: Arc<LanguageRegistry>,
1402    queued_operations: Vec<(u64, Operation)>,
1403    _subscriptions: Vec<client::Subscription>,
1404}
1405
1406impl RemoteWorktree {
1407    pub fn open_buffer(
1408        &mut self,
1409        path: &Path,
1410        cx: &mut ModelContext<Worktree>,
1411    ) -> Task<Result<ModelHandle<Buffer>>> {
1412        let mut existing_buffer = None;
1413        self.open_buffers.retain(|_buffer_id, buffer| {
1414            if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
1415                if let Some(file) = buffer.read(cx.as_ref()).file() {
1416                    if file.worktree_id() == cx.model_id() && file.path().as_ref() == path {
1417                        existing_buffer = Some(buffer);
1418                    }
1419                }
1420                true
1421            } else {
1422                false
1423            }
1424        });
1425
1426        let rpc = self.client.clone();
1427        let replica_id = self.replica_id;
1428        let remote_worktree_id = self.remote_id;
1429        let root_path = self.snapshot.abs_path.clone();
1430        let path = path.to_string_lossy().to_string();
1431        cx.spawn_weak(|this, mut cx| async move {
1432            if let Some(existing_buffer) = existing_buffer {
1433                Ok(existing_buffer)
1434            } else {
1435                let entry = this
1436                    .upgrade(&cx)
1437                    .ok_or_else(|| anyhow!("worktree was closed"))?
1438                    .read_with(&cx, |tree, _| tree.entry_for_path(&path).cloned())
1439                    .ok_or_else(|| anyhow!("file does not exist"))?;
1440                let response = rpc
1441                    .request(proto::OpenBuffer {
1442                        worktree_id: remote_worktree_id as u64,
1443                        path,
1444                    })
1445                    .await?;
1446
1447                let this = this
1448                    .upgrade(&cx)
1449                    .ok_or_else(|| anyhow!("worktree was closed"))?;
1450                let file = File {
1451                    entry_id: Some(entry.id),
1452                    worktree: this.clone(),
1453                    worktree_path: root_path,
1454                    path: entry.path,
1455                    mtime: entry.mtime,
1456                    is_local: false,
1457                };
1458                let language = this.read_with(&cx, |this, _| {
1459                    use language::File;
1460                    this.languages().select_language(file.full_path()).cloned()
1461                });
1462                let remote_buffer = response.buffer.ok_or_else(|| anyhow!("empty buffer"))?;
1463                let buffer_id = remote_buffer.id as usize;
1464                let buffer = cx.add_model(|cx| {
1465                    Buffer::from_proto(replica_id, remote_buffer, Some(Box::new(file)), cx)
1466                        .unwrap()
1467                        .with_language(language, None, cx)
1468                });
1469                this.update(&mut cx, |this, cx| {
1470                    let this = this.as_remote_mut().unwrap();
1471                    if let Some(RemoteBuffer::Operations(pending_ops)) = this
1472                        .open_buffers
1473                        .insert(buffer_id, RemoteBuffer::Loaded(buffer.downgrade()))
1474                    {
1475                        buffer.update(cx, |buf, cx| buf.apply_ops(pending_ops, cx))?;
1476                    }
1477                    Result::<_, anyhow::Error>::Ok(())
1478                })?;
1479                Ok(buffer)
1480            }
1481        })
1482    }
1483
1484    pub fn remote_id(&self) -> u64 {
1485        self.remote_id
1486    }
1487
1488    pub fn close_all_buffers(&mut self, cx: &mut MutableAppContext) {
1489        for (_, buffer) in self.open_buffers.drain() {
1490            if let RemoteBuffer::Loaded(buffer) = buffer {
1491                if let Some(buffer) = buffer.upgrade(cx) {
1492                    buffer.update(cx, |buffer, cx| buffer.close(cx))
1493                }
1494            }
1495        }
1496    }
1497
1498    fn snapshot(&self) -> Snapshot {
1499        self.snapshot.clone()
1500    }
1501
1502    fn update_from_remote(
1503        &mut self,
1504        envelope: TypedEnvelope<proto::UpdateWorktree>,
1505        cx: &mut ModelContext<Worktree>,
1506    ) -> Result<()> {
1507        let mut tx = self.updates_tx.clone();
1508        let payload = envelope.payload.clone();
1509        cx.background()
1510            .spawn(async move {
1511                tx.send(payload).await.expect("receiver runs to completion");
1512            })
1513            .detach();
1514
1515        Ok(())
1516    }
1517
1518    pub fn add_peer(
1519        &mut self,
1520        envelope: TypedEnvelope<proto::AddPeer>,
1521        cx: &mut ModelContext<Worktree>,
1522    ) -> Result<()> {
1523        let peer = envelope
1524            .payload
1525            .peer
1526            .as_ref()
1527            .ok_or_else(|| anyhow!("empty peer"))?;
1528        let peer_id = PeerId(peer.peer_id);
1529        self.collaborators.insert(
1530            peer_id,
1531            Collaborator {
1532                peer_id,
1533                user_id: peer.user_id,
1534                replica_id: peer.replica_id as ReplicaId,
1535            },
1536        );
1537        cx.notify();
1538        Ok(())
1539    }
1540
1541    pub fn remove_peer(
1542        &mut self,
1543        envelope: TypedEnvelope<proto::RemovePeer>,
1544        cx: &mut ModelContext<Worktree>,
1545    ) -> Result<()> {
1546        let peer_id = PeerId(envelope.payload.peer_id);
1547        let replica_id = self
1548            .collaborators
1549            .remove(&peer_id)
1550            .ok_or_else(|| anyhow!("unknown peer {:?}", peer_id))?
1551            .replica_id;
1552        for (_, buffer) in &self.open_buffers {
1553            if let Some(buffer) = buffer.upgrade(cx) {
1554                buffer.update(cx, |buffer, cx| buffer.remove_peer(replica_id, cx));
1555            }
1556        }
1557        cx.notify();
1558        Ok(())
1559    }
1560}
1561
1562enum RemoteBuffer {
1563    Operations(Vec<Operation>),
1564    Loaded(WeakModelHandle<Buffer>),
1565}
1566
1567impl RemoteBuffer {
1568    fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<ModelHandle<Buffer>> {
1569        match self {
1570            Self::Operations(_) => None,
1571            Self::Loaded(buffer) => buffer.upgrade(cx),
1572        }
1573    }
1574}
1575
1576#[derive(Clone)]
1577pub struct Snapshot {
1578    id: usize,
1579    scan_id: usize,
1580    abs_path: Arc<Path>,
1581    root_name: String,
1582    root_char_bag: CharBag,
1583    ignores: HashMap<Arc<Path>, (Arc<Gitignore>, usize)>,
1584    entries_by_path: SumTree<Entry>,
1585    entries_by_id: SumTree<PathEntry>,
1586    removed_entry_ids: HashMap<u64, usize>,
1587    next_entry_id: Arc<AtomicUsize>,
1588}
1589
1590impl Snapshot {
1591    pub fn id(&self) -> usize {
1592        self.id
1593    }
1594
1595    pub fn build_update(
1596        &self,
1597        other: &Self,
1598        worktree_id: u64,
1599        include_ignored: bool,
1600    ) -> proto::UpdateWorktree {
1601        let mut updated_entries = Vec::new();
1602        let mut removed_entries = Vec::new();
1603        let mut self_entries = self
1604            .entries_by_id
1605            .cursor::<()>()
1606            .filter(|e| include_ignored || !e.is_ignored)
1607            .peekable();
1608        let mut other_entries = other
1609            .entries_by_id
1610            .cursor::<()>()
1611            .filter(|e| include_ignored || !e.is_ignored)
1612            .peekable();
1613        loop {
1614            match (self_entries.peek(), other_entries.peek()) {
1615                (Some(self_entry), Some(other_entry)) => {
1616                    match Ord::cmp(&self_entry.id, &other_entry.id) {
1617                        Ordering::Less => {
1618                            let entry = self.entry_for_id(self_entry.id).unwrap().into();
1619                            updated_entries.push(entry);
1620                            self_entries.next();
1621                        }
1622                        Ordering::Equal => {
1623                            if self_entry.scan_id != other_entry.scan_id {
1624                                let entry = self.entry_for_id(self_entry.id).unwrap().into();
1625                                updated_entries.push(entry);
1626                            }
1627
1628                            self_entries.next();
1629                            other_entries.next();
1630                        }
1631                        Ordering::Greater => {
1632                            removed_entries.push(other_entry.id as u64);
1633                            other_entries.next();
1634                        }
1635                    }
1636                }
1637                (Some(self_entry), None) => {
1638                    let entry = self.entry_for_id(self_entry.id).unwrap().into();
1639                    updated_entries.push(entry);
1640                    self_entries.next();
1641                }
1642                (None, Some(other_entry)) => {
1643                    removed_entries.push(other_entry.id as u64);
1644                    other_entries.next();
1645                }
1646                (None, None) => break,
1647            }
1648        }
1649
1650        proto::UpdateWorktree {
1651            updated_entries,
1652            removed_entries,
1653            worktree_id,
1654        }
1655    }
1656
1657    fn apply_update(&mut self, update: proto::UpdateWorktree) -> Result<()> {
1658        self.scan_id += 1;
1659        let scan_id = self.scan_id;
1660
1661        let mut entries_by_path_edits = Vec::new();
1662        let mut entries_by_id_edits = Vec::new();
1663        for entry_id in update.removed_entries {
1664            let entry_id = entry_id as usize;
1665            let entry = self
1666                .entry_for_id(entry_id)
1667                .ok_or_else(|| anyhow!("unknown entry"))?;
1668            entries_by_path_edits.push(Edit::Remove(PathKey(entry.path.clone())));
1669            entries_by_id_edits.push(Edit::Remove(entry.id));
1670        }
1671
1672        for entry in update.updated_entries {
1673            let entry = Entry::try_from((&self.root_char_bag, entry))?;
1674            if let Some(PathEntry { path, .. }) = self.entries_by_id.get(&entry.id, &()) {
1675                entries_by_path_edits.push(Edit::Remove(PathKey(path.clone())));
1676            }
1677            entries_by_id_edits.push(Edit::Insert(PathEntry {
1678                id: entry.id,
1679                path: entry.path.clone(),
1680                is_ignored: entry.is_ignored,
1681                scan_id,
1682            }));
1683            entries_by_path_edits.push(Edit::Insert(entry));
1684        }
1685
1686        self.entries_by_path.edit(entries_by_path_edits, &());
1687        self.entries_by_id.edit(entries_by_id_edits, &());
1688
1689        Ok(())
1690    }
1691
1692    pub fn file_count(&self) -> usize {
1693        self.entries_by_path.summary().file_count
1694    }
1695
1696    pub fn visible_file_count(&self) -> usize {
1697        self.entries_by_path.summary().visible_file_count
1698    }
1699
1700    fn traverse_from_offset(
1701        &self,
1702        include_dirs: bool,
1703        include_ignored: bool,
1704        start_offset: usize,
1705    ) -> Traversal {
1706        let mut cursor = self.entries_by_path.cursor();
1707        cursor.seek(
1708            &TraversalTarget::Count {
1709                count: start_offset,
1710                include_dirs,
1711                include_ignored,
1712            },
1713            Bias::Right,
1714            &(),
1715        );
1716        Traversal {
1717            cursor,
1718            include_dirs,
1719            include_ignored,
1720        }
1721    }
1722
1723    fn traverse_from_path(
1724        &self,
1725        include_dirs: bool,
1726        include_ignored: bool,
1727        path: &Path,
1728    ) -> Traversal {
1729        let mut cursor = self.entries_by_path.cursor();
1730        cursor.seek(&TraversalTarget::Path(path), Bias::Left, &());
1731        Traversal {
1732            cursor,
1733            include_dirs,
1734            include_ignored,
1735        }
1736    }
1737
1738    pub fn files(&self, include_ignored: bool, start: usize) -> Traversal {
1739        self.traverse_from_offset(false, include_ignored, start)
1740    }
1741
1742    pub fn entries(&self, include_ignored: bool) -> Traversal {
1743        self.traverse_from_offset(true, include_ignored, 0)
1744    }
1745
1746    pub fn paths(&self) -> impl Iterator<Item = &Arc<Path>> {
1747        let empty_path = Path::new("");
1748        self.entries_by_path
1749            .cursor::<()>()
1750            .filter(move |entry| entry.path.as_ref() != empty_path)
1751            .map(|entry| &entry.path)
1752    }
1753
1754    fn child_entries<'a>(&'a self, parent_path: &'a Path) -> ChildEntriesIter<'a> {
1755        let mut cursor = self.entries_by_path.cursor();
1756        cursor.seek(&TraversalTarget::Path(parent_path), Bias::Right, &());
1757        let traversal = Traversal {
1758            cursor,
1759            include_dirs: true,
1760            include_ignored: true,
1761        };
1762        ChildEntriesIter {
1763            traversal,
1764            parent_path,
1765        }
1766    }
1767
1768    pub fn root_entry(&self) -> Option<&Entry> {
1769        self.entry_for_path("")
1770    }
1771
1772    pub fn root_name(&self) -> &str {
1773        &self.root_name
1774    }
1775
1776    pub fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> {
1777        let path = path.as_ref();
1778        self.traverse_from_path(true, true, path)
1779            .entry()
1780            .and_then(|entry| {
1781                if entry.path.as_ref() == path {
1782                    Some(entry)
1783                } else {
1784                    None
1785                }
1786            })
1787    }
1788
1789    pub fn entry_for_id(&self, id: usize) -> Option<&Entry> {
1790        let entry = self.entries_by_id.get(&id, &())?;
1791        self.entry_for_path(&entry.path)
1792    }
1793
1794    pub fn inode_for_path(&self, path: impl AsRef<Path>) -> Option<u64> {
1795        self.entry_for_path(path.as_ref()).map(|e| e.inode)
1796    }
1797
1798    fn insert_entry(&mut self, mut entry: Entry, fs: &dyn Fs) -> Entry {
1799        if !entry.is_dir() && entry.path.file_name() == Some(&GITIGNORE) {
1800            let abs_path = self.abs_path.join(&entry.path);
1801            match build_gitignore(&abs_path, fs) {
1802                Ok(ignore) => {
1803                    let ignore_dir_path = entry.path.parent().unwrap();
1804                    self.ignores
1805                        .insert(ignore_dir_path.into(), (Arc::new(ignore), self.scan_id));
1806                }
1807                Err(error) => {
1808                    log::error!(
1809                        "error loading .gitignore file {:?} - {:?}",
1810                        &entry.path,
1811                        error
1812                    );
1813                }
1814            }
1815        }
1816
1817        self.reuse_entry_id(&mut entry);
1818        self.entries_by_path.insert_or_replace(entry.clone(), &());
1819        self.entries_by_id.insert_or_replace(
1820            PathEntry {
1821                id: entry.id,
1822                path: entry.path.clone(),
1823                is_ignored: entry.is_ignored,
1824                scan_id: self.scan_id,
1825            },
1826            &(),
1827        );
1828        entry
1829    }
1830
1831    fn populate_dir(
1832        &mut self,
1833        parent_path: Arc<Path>,
1834        entries: impl IntoIterator<Item = Entry>,
1835        ignore: Option<Arc<Gitignore>>,
1836    ) {
1837        let mut parent_entry = self
1838            .entries_by_path
1839            .get(&PathKey(parent_path.clone()), &())
1840            .unwrap()
1841            .clone();
1842        if let Some(ignore) = ignore {
1843            self.ignores.insert(parent_path, (ignore, self.scan_id));
1844        }
1845        if matches!(parent_entry.kind, EntryKind::PendingDir) {
1846            parent_entry.kind = EntryKind::Dir;
1847        } else {
1848            unreachable!();
1849        }
1850
1851        let mut entries_by_path_edits = vec![Edit::Insert(parent_entry)];
1852        let mut entries_by_id_edits = Vec::new();
1853
1854        for mut entry in entries {
1855            self.reuse_entry_id(&mut entry);
1856            entries_by_id_edits.push(Edit::Insert(PathEntry {
1857                id: entry.id,
1858                path: entry.path.clone(),
1859                is_ignored: entry.is_ignored,
1860                scan_id: self.scan_id,
1861            }));
1862            entries_by_path_edits.push(Edit::Insert(entry));
1863        }
1864
1865        self.entries_by_path.edit(entries_by_path_edits, &());
1866        self.entries_by_id.edit(entries_by_id_edits, &());
1867    }
1868
1869    fn reuse_entry_id(&mut self, entry: &mut Entry) {
1870        if let Some(removed_entry_id) = self.removed_entry_ids.remove(&entry.inode) {
1871            entry.id = removed_entry_id;
1872        } else if let Some(existing_entry) = self.entry_for_path(&entry.path) {
1873            entry.id = existing_entry.id;
1874        }
1875    }
1876
1877    fn remove_path(&mut self, path: &Path) {
1878        let mut new_entries;
1879        let removed_entries;
1880        {
1881            let mut cursor = self.entries_by_path.cursor::<TraversalProgress>();
1882            new_entries = cursor.slice(&TraversalTarget::Path(path), Bias::Left, &());
1883            removed_entries = cursor.slice(&TraversalTarget::PathSuccessor(path), Bias::Left, &());
1884            new_entries.push_tree(cursor.suffix(&()), &());
1885        }
1886        self.entries_by_path = new_entries;
1887
1888        let mut entries_by_id_edits = Vec::new();
1889        for entry in removed_entries.cursor::<()>() {
1890            let removed_entry_id = self
1891                .removed_entry_ids
1892                .entry(entry.inode)
1893                .or_insert(entry.id);
1894            *removed_entry_id = cmp::max(*removed_entry_id, entry.id);
1895            entries_by_id_edits.push(Edit::Remove(entry.id));
1896        }
1897        self.entries_by_id.edit(entries_by_id_edits, &());
1898
1899        if path.file_name() == Some(&GITIGNORE) {
1900            if let Some((_, scan_id)) = self.ignores.get_mut(path.parent().unwrap()) {
1901                *scan_id = self.scan_id;
1902            }
1903        }
1904    }
1905
1906    fn ignore_stack_for_path(&self, path: &Path, is_dir: bool) -> Arc<IgnoreStack> {
1907        let mut new_ignores = Vec::new();
1908        for ancestor in path.ancestors().skip(1) {
1909            if let Some((ignore, _)) = self.ignores.get(ancestor) {
1910                new_ignores.push((ancestor, Some(ignore.clone())));
1911            } else {
1912                new_ignores.push((ancestor, None));
1913            }
1914        }
1915
1916        let mut ignore_stack = IgnoreStack::none();
1917        for (parent_path, ignore) in new_ignores.into_iter().rev() {
1918            if ignore_stack.is_path_ignored(&parent_path, true) {
1919                ignore_stack = IgnoreStack::all();
1920                break;
1921            } else if let Some(ignore) = ignore {
1922                ignore_stack = ignore_stack.append(Arc::from(parent_path), ignore);
1923            }
1924        }
1925
1926        if ignore_stack.is_path_ignored(path, is_dir) {
1927            ignore_stack = IgnoreStack::all();
1928        }
1929
1930        ignore_stack
1931    }
1932}
1933
1934impl fmt::Debug for Snapshot {
1935    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1936        for entry in self.entries_by_path.cursor::<()>() {
1937            for _ in entry.path.ancestors().skip(1) {
1938                write!(f, " ")?;
1939            }
1940            writeln!(f, "{:?} (inode: {})", entry.path, entry.inode)?;
1941        }
1942        Ok(())
1943    }
1944}
1945
1946#[derive(Clone, PartialEq)]
1947pub struct File {
1948    entry_id: Option<usize>,
1949    worktree: ModelHandle<Worktree>,
1950    worktree_path: Arc<Path>,
1951    pub path: Arc<Path>,
1952    pub mtime: SystemTime,
1953    is_local: bool,
1954}
1955
1956impl language::File for File {
1957    fn worktree_id(&self) -> usize {
1958        self.worktree.id()
1959    }
1960
1961    fn entry_id(&self) -> Option<usize> {
1962        self.entry_id
1963    }
1964
1965    fn mtime(&self) -> SystemTime {
1966        self.mtime
1967    }
1968
1969    fn path(&self) -> &Arc<Path> {
1970        &self.path
1971    }
1972
1973    fn abs_path(&self) -> Option<PathBuf> {
1974        if self.is_local {
1975            Some(self.worktree_path.join(&self.path))
1976        } else {
1977            None
1978        }
1979    }
1980
1981    fn full_path(&self) -> PathBuf {
1982        let mut full_path = PathBuf::new();
1983        if let Some(worktree_name) = self.worktree_path.file_name() {
1984            full_path.push(worktree_name);
1985        }
1986        full_path.push(&self.path);
1987        full_path
1988    }
1989
1990    /// Returns the last component of this handle's absolute path. If this handle refers to the root
1991    /// of its worktree, then this method will return the name of the worktree itself.
1992    fn file_name<'a>(&'a self) -> Option<OsString> {
1993        self.path
1994            .file_name()
1995            .or_else(|| self.worktree_path.file_name())
1996            .map(Into::into)
1997    }
1998
1999    fn is_deleted(&self) -> bool {
2000        self.entry_id.is_none()
2001    }
2002
2003    fn save(
2004        &self,
2005        buffer_id: u64,
2006        text: Rope,
2007        version: clock::Global,
2008        cx: &mut MutableAppContext,
2009    ) -> Task<Result<(clock::Global, SystemTime)>> {
2010        self.worktree.update(cx, |worktree, cx| match worktree {
2011            Worktree::Local(worktree) => {
2012                let rpc = worktree.rpc.clone();
2013                let worktree_id = *worktree.remote_id.borrow();
2014                let save = worktree.save(self.path.clone(), text, cx);
2015                cx.background().spawn(async move {
2016                    let entry = save.await?;
2017                    if let Some(worktree_id) = worktree_id {
2018                        rpc.send(proto::BufferSaved {
2019                            worktree_id,
2020                            buffer_id,
2021                            version: (&version).into(),
2022                            mtime: Some(entry.mtime.into()),
2023                        })
2024                        .await?;
2025                    }
2026                    Ok((version, entry.mtime))
2027                })
2028            }
2029            Worktree::Remote(worktree) => {
2030                let rpc = worktree.client.clone();
2031                let worktree_id = worktree.remote_id;
2032                cx.foreground().spawn(async move {
2033                    let response = rpc
2034                        .request(proto::SaveBuffer {
2035                            worktree_id,
2036                            buffer_id,
2037                        })
2038                        .await?;
2039                    let version = response.version.try_into()?;
2040                    let mtime = response
2041                        .mtime
2042                        .ok_or_else(|| anyhow!("missing mtime"))?
2043                        .into();
2044                    Ok((version, mtime))
2045                })
2046            }
2047        })
2048    }
2049
2050    fn load_local(&self, cx: &AppContext) -> Option<Task<Result<String>>> {
2051        let worktree = self.worktree.read(cx).as_local()?;
2052        let abs_path = worktree.absolutize(&self.path);
2053        let fs = worktree.fs.clone();
2054        Some(
2055            cx.background()
2056                .spawn(async move { fs.load(&abs_path).await }),
2057        )
2058    }
2059
2060    fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext) {
2061        self.worktree.update(cx, |worktree, cx| {
2062            worktree.send_buffer_update(buffer_id, operation, cx);
2063        });
2064    }
2065
2066    fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext) {
2067        self.worktree.update(cx, |worktree, cx| {
2068            if let Worktree::Remote(worktree) = worktree {
2069                let worktree_id = worktree.remote_id;
2070                let rpc = worktree.client.clone();
2071                cx.background()
2072                    .spawn(async move {
2073                        if let Err(error) = rpc
2074                            .send(proto::CloseBuffer {
2075                                worktree_id,
2076                                buffer_id,
2077                            })
2078                            .await
2079                        {
2080                            log::error!("error closing remote buffer: {}", error);
2081                        }
2082                    })
2083                    .detach();
2084            }
2085        });
2086    }
2087
2088    fn boxed_clone(&self) -> Box<dyn language::File> {
2089        Box::new(self.clone())
2090    }
2091
2092    fn as_any(&self) -> &dyn Any {
2093        self
2094    }
2095}
2096
2097#[derive(Clone, Debug)]
2098pub struct Entry {
2099    pub id: usize,
2100    pub kind: EntryKind,
2101    pub path: Arc<Path>,
2102    pub inode: u64,
2103    pub mtime: SystemTime,
2104    pub is_symlink: bool,
2105    pub is_ignored: bool,
2106}
2107
2108#[derive(Clone, Debug)]
2109pub enum EntryKind {
2110    PendingDir,
2111    Dir,
2112    File(CharBag),
2113}
2114
2115impl Entry {
2116    fn new(
2117        path: Arc<Path>,
2118        metadata: &fs::Metadata,
2119        next_entry_id: &AtomicUsize,
2120        root_char_bag: CharBag,
2121    ) -> Self {
2122        Self {
2123            id: next_entry_id.fetch_add(1, SeqCst),
2124            kind: if metadata.is_dir {
2125                EntryKind::PendingDir
2126            } else {
2127                EntryKind::File(char_bag_for_path(root_char_bag, &path))
2128            },
2129            path,
2130            inode: metadata.inode,
2131            mtime: metadata.mtime,
2132            is_symlink: metadata.is_symlink,
2133            is_ignored: false,
2134        }
2135    }
2136
2137    pub fn is_dir(&self) -> bool {
2138        matches!(self.kind, EntryKind::Dir | EntryKind::PendingDir)
2139    }
2140
2141    pub fn is_file(&self) -> bool {
2142        matches!(self.kind, EntryKind::File(_))
2143    }
2144}
2145
2146impl sum_tree::Item for Entry {
2147    type Summary = EntrySummary;
2148
2149    fn summary(&self) -> Self::Summary {
2150        let visible_count = if self.is_ignored { 0 } else { 1 };
2151        let file_count;
2152        let visible_file_count;
2153        if self.is_file() {
2154            file_count = 1;
2155            visible_file_count = visible_count;
2156        } else {
2157            file_count = 0;
2158            visible_file_count = 0;
2159        }
2160
2161        EntrySummary {
2162            max_path: self.path.clone(),
2163            count: 1,
2164            visible_count,
2165            file_count,
2166            visible_file_count,
2167        }
2168    }
2169}
2170
2171impl sum_tree::KeyedItem for Entry {
2172    type Key = PathKey;
2173
2174    fn key(&self) -> Self::Key {
2175        PathKey(self.path.clone())
2176    }
2177}
2178
2179#[derive(Clone, Debug)]
2180pub struct EntrySummary {
2181    max_path: Arc<Path>,
2182    count: usize,
2183    visible_count: usize,
2184    file_count: usize,
2185    visible_file_count: usize,
2186}
2187
2188impl Default for EntrySummary {
2189    fn default() -> Self {
2190        Self {
2191            max_path: Arc::from(Path::new("")),
2192            count: 0,
2193            visible_count: 0,
2194            file_count: 0,
2195            visible_file_count: 0,
2196        }
2197    }
2198}
2199
2200impl sum_tree::Summary for EntrySummary {
2201    type Context = ();
2202
2203    fn add_summary(&mut self, rhs: &Self, _: &()) {
2204        self.max_path = rhs.max_path.clone();
2205        self.visible_count += rhs.visible_count;
2206        self.file_count += rhs.file_count;
2207        self.visible_file_count += rhs.visible_file_count;
2208    }
2209}
2210
2211#[derive(Clone, Debug)]
2212struct PathEntry {
2213    id: usize,
2214    path: Arc<Path>,
2215    is_ignored: bool,
2216    scan_id: usize,
2217}
2218
2219impl sum_tree::Item for PathEntry {
2220    type Summary = PathEntrySummary;
2221
2222    fn summary(&self) -> Self::Summary {
2223        PathEntrySummary { max_id: self.id }
2224    }
2225}
2226
2227impl sum_tree::KeyedItem for PathEntry {
2228    type Key = usize;
2229
2230    fn key(&self) -> Self::Key {
2231        self.id
2232    }
2233}
2234
2235#[derive(Clone, Debug, Default)]
2236struct PathEntrySummary {
2237    max_id: usize,
2238}
2239
2240impl sum_tree::Summary for PathEntrySummary {
2241    type Context = ();
2242
2243    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
2244        self.max_id = summary.max_id;
2245    }
2246}
2247
2248impl<'a> sum_tree::Dimension<'a, PathEntrySummary> for usize {
2249    fn add_summary(&mut self, summary: &'a PathEntrySummary, _: &()) {
2250        *self = summary.max_id;
2251    }
2252}
2253
2254#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
2255pub struct PathKey(Arc<Path>);
2256
2257impl Default for PathKey {
2258    fn default() -> Self {
2259        Self(Path::new("").into())
2260    }
2261}
2262
2263impl<'a> sum_tree::Dimension<'a, EntrySummary> for PathKey {
2264    fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
2265        self.0 = summary.max_path.clone();
2266    }
2267}
2268
2269struct BackgroundScanner {
2270    fs: Arc<dyn Fs>,
2271    snapshot: Arc<Mutex<Snapshot>>,
2272    notify: Sender<ScanState>,
2273    executor: Arc<executor::Background>,
2274}
2275
2276impl BackgroundScanner {
2277    fn new(
2278        snapshot: Arc<Mutex<Snapshot>>,
2279        notify: Sender<ScanState>,
2280        fs: Arc<dyn Fs>,
2281        executor: Arc<executor::Background>,
2282    ) -> Self {
2283        Self {
2284            fs,
2285            snapshot,
2286            notify,
2287            executor,
2288        }
2289    }
2290
2291    fn abs_path(&self) -> Arc<Path> {
2292        self.snapshot.lock().abs_path.clone()
2293    }
2294
2295    fn snapshot(&self) -> Snapshot {
2296        self.snapshot.lock().clone()
2297    }
2298
2299    async fn run(mut self, events_rx: impl Stream<Item = Vec<fsevent::Event>>) {
2300        if self.notify.send(ScanState::Scanning).await.is_err() {
2301            return;
2302        }
2303
2304        if let Err(err) = self.scan_dirs().await {
2305            if self
2306                .notify
2307                .send(ScanState::Err(Arc::new(err)))
2308                .await
2309                .is_err()
2310            {
2311                return;
2312            }
2313        }
2314
2315        if self.notify.send(ScanState::Idle).await.is_err() {
2316            return;
2317        }
2318
2319        futures::pin_mut!(events_rx);
2320        while let Some(events) = events_rx.next().await {
2321            if self.notify.send(ScanState::Scanning).await.is_err() {
2322                break;
2323            }
2324
2325            if !self.process_events(events).await {
2326                break;
2327            }
2328
2329            if self.notify.send(ScanState::Idle).await.is_err() {
2330                break;
2331            }
2332        }
2333    }
2334
2335    async fn scan_dirs(&mut self) -> Result<()> {
2336        let root_char_bag;
2337        let next_entry_id;
2338        let is_dir;
2339        {
2340            let snapshot = self.snapshot.lock();
2341            root_char_bag = snapshot.root_char_bag;
2342            next_entry_id = snapshot.next_entry_id.clone();
2343            is_dir = snapshot.root_entry().map_or(false, |e| e.is_dir())
2344        };
2345
2346        if is_dir {
2347            let path: Arc<Path> = Arc::from(Path::new(""));
2348            let abs_path = self.abs_path();
2349            let (tx, rx) = channel::unbounded();
2350            tx.send(ScanJob {
2351                abs_path: abs_path.to_path_buf(),
2352                path,
2353                ignore_stack: IgnoreStack::none(),
2354                scan_queue: tx.clone(),
2355            })
2356            .await
2357            .unwrap();
2358            drop(tx);
2359
2360            self.executor
2361                .scoped(|scope| {
2362                    for _ in 0..self.executor.num_cpus() {
2363                        scope.spawn(async {
2364                            while let Ok(job) = rx.recv().await {
2365                                if let Err(err) = self
2366                                    .scan_dir(root_char_bag, next_entry_id.clone(), &job)
2367                                    .await
2368                                {
2369                                    log::error!("error scanning {:?}: {}", job.abs_path, err);
2370                                }
2371                            }
2372                        });
2373                    }
2374                })
2375                .await;
2376        }
2377
2378        Ok(())
2379    }
2380
2381    async fn scan_dir(
2382        &self,
2383        root_char_bag: CharBag,
2384        next_entry_id: Arc<AtomicUsize>,
2385        job: &ScanJob,
2386    ) -> Result<()> {
2387        let mut new_entries: Vec<Entry> = Vec::new();
2388        let mut new_jobs: Vec<ScanJob> = Vec::new();
2389        let mut ignore_stack = job.ignore_stack.clone();
2390        let mut new_ignore = None;
2391
2392        let mut child_paths = self.fs.read_dir(&job.abs_path).await?;
2393        while let Some(child_abs_path) = child_paths.next().await {
2394            let child_abs_path = match child_abs_path {
2395                Ok(child_abs_path) => child_abs_path,
2396                Err(error) => {
2397                    log::error!("error processing entry {:?}", error);
2398                    continue;
2399                }
2400            };
2401            let child_name = child_abs_path.file_name().unwrap();
2402            let child_path: Arc<Path> = job.path.join(child_name).into();
2403            let child_metadata = match self.fs.metadata(&child_abs_path).await? {
2404                Some(metadata) => metadata,
2405                None => continue,
2406            };
2407
2408            // If we find a .gitignore, add it to the stack of ignores used to determine which paths are ignored
2409            if child_name == *GITIGNORE {
2410                match build_gitignore(&child_abs_path, self.fs.as_ref()) {
2411                    Ok(ignore) => {
2412                        let ignore = Arc::new(ignore);
2413                        ignore_stack = ignore_stack.append(job.path.clone(), ignore.clone());
2414                        new_ignore = Some(ignore);
2415                    }
2416                    Err(error) => {
2417                        log::error!(
2418                            "error loading .gitignore file {:?} - {:?}",
2419                            child_name,
2420                            error
2421                        );
2422                    }
2423                }
2424
2425                // Update ignore status of any child entries we've already processed to reflect the
2426                // ignore file in the current directory. Because `.gitignore` starts with a `.`,
2427                // there should rarely be too numerous. Update the ignore stack associated with any
2428                // new jobs as well.
2429                let mut new_jobs = new_jobs.iter_mut();
2430                for entry in &mut new_entries {
2431                    entry.is_ignored = ignore_stack.is_path_ignored(&entry.path, entry.is_dir());
2432                    if entry.is_dir() {
2433                        new_jobs.next().unwrap().ignore_stack = if entry.is_ignored {
2434                            IgnoreStack::all()
2435                        } else {
2436                            ignore_stack.clone()
2437                        };
2438                    }
2439                }
2440            }
2441
2442            let mut child_entry = Entry::new(
2443                child_path.clone(),
2444                &child_metadata,
2445                &next_entry_id,
2446                root_char_bag,
2447            );
2448
2449            if child_metadata.is_dir {
2450                let is_ignored = ignore_stack.is_path_ignored(&child_path, true);
2451                child_entry.is_ignored = is_ignored;
2452                new_entries.push(child_entry);
2453                new_jobs.push(ScanJob {
2454                    abs_path: child_abs_path,
2455                    path: child_path,
2456                    ignore_stack: if is_ignored {
2457                        IgnoreStack::all()
2458                    } else {
2459                        ignore_stack.clone()
2460                    },
2461                    scan_queue: job.scan_queue.clone(),
2462                });
2463            } else {
2464                child_entry.is_ignored = ignore_stack.is_path_ignored(&child_path, false);
2465                new_entries.push(child_entry);
2466            };
2467        }
2468
2469        self.snapshot
2470            .lock()
2471            .populate_dir(job.path.clone(), new_entries, new_ignore);
2472        for new_job in new_jobs {
2473            job.scan_queue.send(new_job).await.unwrap();
2474        }
2475
2476        Ok(())
2477    }
2478
2479    async fn process_events(&mut self, mut events: Vec<fsevent::Event>) -> bool {
2480        let mut snapshot = self.snapshot();
2481        snapshot.scan_id += 1;
2482
2483        let root_abs_path = if let Ok(abs_path) = self.fs.canonicalize(&snapshot.abs_path).await {
2484            abs_path
2485        } else {
2486            return false;
2487        };
2488        let root_char_bag = snapshot.root_char_bag;
2489        let next_entry_id = snapshot.next_entry_id.clone();
2490
2491        events.sort_unstable_by(|a, b| a.path.cmp(&b.path));
2492        events.dedup_by(|a, b| a.path.starts_with(&b.path));
2493
2494        for event in &events {
2495            match event.path.strip_prefix(&root_abs_path) {
2496                Ok(path) => snapshot.remove_path(&path),
2497                Err(_) => {
2498                    log::error!(
2499                        "unexpected event {:?} for root path {:?}",
2500                        event.path,
2501                        root_abs_path
2502                    );
2503                    continue;
2504                }
2505            }
2506        }
2507
2508        let (scan_queue_tx, scan_queue_rx) = channel::unbounded();
2509        for event in events {
2510            let path: Arc<Path> = match event.path.strip_prefix(&root_abs_path) {
2511                Ok(path) => Arc::from(path.to_path_buf()),
2512                Err(_) => {
2513                    log::error!(
2514                        "unexpected event {:?} for root path {:?}",
2515                        event.path,
2516                        root_abs_path
2517                    );
2518                    continue;
2519                }
2520            };
2521
2522            match self.fs.metadata(&event.path).await {
2523                Ok(Some(metadata)) => {
2524                    let ignore_stack = snapshot.ignore_stack_for_path(&path, metadata.is_dir);
2525                    let mut fs_entry = Entry::new(
2526                        path.clone(),
2527                        &metadata,
2528                        snapshot.next_entry_id.as_ref(),
2529                        snapshot.root_char_bag,
2530                    );
2531                    fs_entry.is_ignored = ignore_stack.is_all();
2532                    snapshot.insert_entry(fs_entry, self.fs.as_ref());
2533                    if metadata.is_dir {
2534                        scan_queue_tx
2535                            .send(ScanJob {
2536                                abs_path: event.path,
2537                                path,
2538                                ignore_stack,
2539                                scan_queue: scan_queue_tx.clone(),
2540                            })
2541                            .await
2542                            .unwrap();
2543                    }
2544                }
2545                Ok(None) => {}
2546                Err(err) => {
2547                    // TODO - create a special 'error' entry in the entries tree to mark this
2548                    log::error!("error reading file on event {:?}", err);
2549                }
2550            }
2551        }
2552
2553        *self.snapshot.lock() = snapshot;
2554
2555        // Scan any directories that were created as part of this event batch.
2556        drop(scan_queue_tx);
2557        self.executor
2558            .scoped(|scope| {
2559                for _ in 0..self.executor.num_cpus() {
2560                    scope.spawn(async {
2561                        while let Ok(job) = scan_queue_rx.recv().await {
2562                            if let Err(err) = self
2563                                .scan_dir(root_char_bag, next_entry_id.clone(), &job)
2564                                .await
2565                            {
2566                                log::error!("error scanning {:?}: {}", job.abs_path, err);
2567                            }
2568                        }
2569                    });
2570                }
2571            })
2572            .await;
2573
2574        // Attempt to detect renames only over a single batch of file-system events.
2575        self.snapshot.lock().removed_entry_ids.clear();
2576
2577        self.update_ignore_statuses().await;
2578        true
2579    }
2580
2581    async fn update_ignore_statuses(&self) {
2582        let mut snapshot = self.snapshot();
2583
2584        let mut ignores_to_update = Vec::new();
2585        let mut ignores_to_delete = Vec::new();
2586        for (parent_path, (_, scan_id)) in &snapshot.ignores {
2587            if *scan_id == snapshot.scan_id && snapshot.entry_for_path(parent_path).is_some() {
2588                ignores_to_update.push(parent_path.clone());
2589            }
2590
2591            let ignore_path = parent_path.join(&*GITIGNORE);
2592            if snapshot.entry_for_path(ignore_path).is_none() {
2593                ignores_to_delete.push(parent_path.clone());
2594            }
2595        }
2596
2597        for parent_path in ignores_to_delete {
2598            snapshot.ignores.remove(&parent_path);
2599            self.snapshot.lock().ignores.remove(&parent_path);
2600        }
2601
2602        let (ignore_queue_tx, ignore_queue_rx) = channel::unbounded();
2603        ignores_to_update.sort_unstable();
2604        let mut ignores_to_update = ignores_to_update.into_iter().peekable();
2605        while let Some(parent_path) = ignores_to_update.next() {
2606            while ignores_to_update
2607                .peek()
2608                .map_or(false, |p| p.starts_with(&parent_path))
2609            {
2610                ignores_to_update.next().unwrap();
2611            }
2612
2613            let ignore_stack = snapshot.ignore_stack_for_path(&parent_path, true);
2614            ignore_queue_tx
2615                .send(UpdateIgnoreStatusJob {
2616                    path: parent_path,
2617                    ignore_stack,
2618                    ignore_queue: ignore_queue_tx.clone(),
2619                })
2620                .await
2621                .unwrap();
2622        }
2623        drop(ignore_queue_tx);
2624
2625        self.executor
2626            .scoped(|scope| {
2627                for _ in 0..self.executor.num_cpus() {
2628                    scope.spawn(async {
2629                        while let Ok(job) = ignore_queue_rx.recv().await {
2630                            self.update_ignore_status(job, &snapshot).await;
2631                        }
2632                    });
2633                }
2634            })
2635            .await;
2636    }
2637
2638    async fn update_ignore_status(&self, job: UpdateIgnoreStatusJob, snapshot: &Snapshot) {
2639        let mut ignore_stack = job.ignore_stack;
2640        if let Some((ignore, _)) = snapshot.ignores.get(&job.path) {
2641            ignore_stack = ignore_stack.append(job.path.clone(), ignore.clone());
2642        }
2643
2644        let mut entries_by_id_edits = Vec::new();
2645        let mut entries_by_path_edits = Vec::new();
2646        for mut entry in snapshot.child_entries(&job.path).cloned() {
2647            let was_ignored = entry.is_ignored;
2648            entry.is_ignored = ignore_stack.is_path_ignored(&entry.path, entry.is_dir());
2649            if entry.is_dir() {
2650                let child_ignore_stack = if entry.is_ignored {
2651                    IgnoreStack::all()
2652                } else {
2653                    ignore_stack.clone()
2654                };
2655                job.ignore_queue
2656                    .send(UpdateIgnoreStatusJob {
2657                        path: entry.path.clone(),
2658                        ignore_stack: child_ignore_stack,
2659                        ignore_queue: job.ignore_queue.clone(),
2660                    })
2661                    .await
2662                    .unwrap();
2663            }
2664
2665            if entry.is_ignored != was_ignored {
2666                let mut path_entry = snapshot.entries_by_id.get(&entry.id, &()).unwrap().clone();
2667                path_entry.scan_id = snapshot.scan_id;
2668                path_entry.is_ignored = entry.is_ignored;
2669                entries_by_id_edits.push(Edit::Insert(path_entry));
2670                entries_by_path_edits.push(Edit::Insert(entry));
2671            }
2672        }
2673
2674        let mut snapshot = self.snapshot.lock();
2675        snapshot.entries_by_path.edit(entries_by_path_edits, &());
2676        snapshot.entries_by_id.edit(entries_by_id_edits, &());
2677    }
2678}
2679
2680async fn refresh_entry(
2681    fs: &dyn Fs,
2682    snapshot: &Mutex<Snapshot>,
2683    path: Arc<Path>,
2684    abs_path: &Path,
2685) -> Result<Entry> {
2686    let root_char_bag;
2687    let next_entry_id;
2688    {
2689        let snapshot = snapshot.lock();
2690        root_char_bag = snapshot.root_char_bag;
2691        next_entry_id = snapshot.next_entry_id.clone();
2692    }
2693    let entry = Entry::new(
2694        path,
2695        &fs.metadata(abs_path)
2696            .await?
2697            .ok_or_else(|| anyhow!("could not read saved file metadata"))?,
2698        &next_entry_id,
2699        root_char_bag,
2700    );
2701    Ok(snapshot.lock().insert_entry(entry, fs))
2702}
2703
2704fn char_bag_for_path(root_char_bag: CharBag, path: &Path) -> CharBag {
2705    let mut result = root_char_bag;
2706    result.extend(
2707        path.to_string_lossy()
2708            .chars()
2709            .map(|c| c.to_ascii_lowercase()),
2710    );
2711    result
2712}
2713
2714struct ScanJob {
2715    abs_path: PathBuf,
2716    path: Arc<Path>,
2717    ignore_stack: Arc<IgnoreStack>,
2718    scan_queue: Sender<ScanJob>,
2719}
2720
2721struct UpdateIgnoreStatusJob {
2722    path: Arc<Path>,
2723    ignore_stack: Arc<IgnoreStack>,
2724    ignore_queue: Sender<UpdateIgnoreStatusJob>,
2725}
2726
2727pub trait WorktreeHandle {
2728    #[cfg(test)]
2729    fn flush_fs_events<'a>(
2730        &self,
2731        cx: &'a gpui::TestAppContext,
2732    ) -> futures::future::LocalBoxFuture<'a, ()>;
2733}
2734
2735impl WorktreeHandle for ModelHandle<Worktree> {
2736    // When the worktree's FS event stream sometimes delivers "redundant" events for FS changes that
2737    // occurred before the worktree was constructed. These events can cause the worktree to perfrom
2738    // extra directory scans, and emit extra scan-state notifications.
2739    //
2740    // This function mutates the worktree's directory and waits for those mutations to be picked up,
2741    // to ensure that all redundant FS events have already been processed.
2742    #[cfg(test)]
2743    fn flush_fs_events<'a>(
2744        &self,
2745        cx: &'a gpui::TestAppContext,
2746    ) -> futures::future::LocalBoxFuture<'a, ()> {
2747        use smol::future::FutureExt;
2748
2749        let filename = "fs-event-sentinel";
2750        let root_path = cx.read(|cx| self.read(cx).abs_path.clone());
2751        let tree = self.clone();
2752        async move {
2753            std::fs::write(root_path.join(filename), "").unwrap();
2754            tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_some())
2755                .await;
2756
2757            std::fs::remove_file(root_path.join(filename)).unwrap();
2758            tree.condition(&cx, |tree, _| tree.entry_for_path(filename).is_none())
2759                .await;
2760
2761            cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
2762                .await;
2763        }
2764        .boxed_local()
2765    }
2766}
2767
2768#[derive(Clone, Debug)]
2769struct TraversalProgress<'a> {
2770    max_path: &'a Path,
2771    count: usize,
2772    visible_count: usize,
2773    file_count: usize,
2774    visible_file_count: usize,
2775}
2776
2777impl<'a> TraversalProgress<'a> {
2778    fn count(&self, include_dirs: bool, include_ignored: bool) -> usize {
2779        match (include_ignored, include_dirs) {
2780            (true, true) => self.count,
2781            (true, false) => self.file_count,
2782            (false, true) => self.visible_count,
2783            (false, false) => self.visible_file_count,
2784        }
2785    }
2786}
2787
2788impl<'a> sum_tree::Dimension<'a, EntrySummary> for TraversalProgress<'a> {
2789    fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
2790        self.max_path = summary.max_path.as_ref();
2791        self.count += summary.count;
2792        self.visible_count += summary.visible_count;
2793        self.file_count += summary.file_count;
2794        self.visible_file_count += summary.visible_file_count;
2795    }
2796}
2797
2798impl<'a> Default for TraversalProgress<'a> {
2799    fn default() -> Self {
2800        Self {
2801            max_path: Path::new(""),
2802            count: 0,
2803            visible_count: 0,
2804            file_count: 0,
2805            visible_file_count: 0,
2806        }
2807    }
2808}
2809
2810pub struct Traversal<'a> {
2811    cursor: sum_tree::Cursor<'a, Entry, TraversalProgress<'a>>,
2812    include_ignored: bool,
2813    include_dirs: bool,
2814}
2815
2816impl<'a> Traversal<'a> {
2817    pub fn advance(&mut self) -> bool {
2818        self.advance_to_offset(self.offset() + 1)
2819    }
2820
2821    pub fn advance_to_offset(&mut self, offset: usize) -> bool {
2822        self.cursor.seek_forward(
2823            &TraversalTarget::Count {
2824                count: offset,
2825                include_dirs: self.include_dirs,
2826                include_ignored: self.include_ignored,
2827            },
2828            Bias::Right,
2829            &(),
2830        )
2831    }
2832
2833    pub fn advance_to_sibling(&mut self) -> bool {
2834        while let Some(entry) = self.cursor.item() {
2835            self.cursor.seek_forward(
2836                &TraversalTarget::PathSuccessor(&entry.path),
2837                Bias::Left,
2838                &(),
2839            );
2840            if let Some(entry) = self.cursor.item() {
2841                if (self.include_dirs || !entry.is_dir())
2842                    && (self.include_ignored || !entry.is_ignored)
2843                {
2844                    return true;
2845                }
2846            }
2847        }
2848        false
2849    }
2850
2851    pub fn entry(&self) -> Option<&'a Entry> {
2852        self.cursor.item()
2853    }
2854
2855    pub fn offset(&self) -> usize {
2856        self.cursor
2857            .start()
2858            .count(self.include_dirs, self.include_ignored)
2859    }
2860}
2861
2862impl<'a> Iterator for Traversal<'a> {
2863    type Item = &'a Entry;
2864
2865    fn next(&mut self) -> Option<Self::Item> {
2866        if let Some(item) = self.entry() {
2867            self.advance();
2868            Some(item)
2869        } else {
2870            None
2871        }
2872    }
2873}
2874
2875#[derive(Debug)]
2876enum TraversalTarget<'a> {
2877    Path(&'a Path),
2878    PathSuccessor(&'a Path),
2879    Count {
2880        count: usize,
2881        include_ignored: bool,
2882        include_dirs: bool,
2883    },
2884}
2885
2886impl<'a, 'b> SeekTarget<'a, EntrySummary, TraversalProgress<'a>> for TraversalTarget<'b> {
2887    fn cmp(&self, cursor_location: &TraversalProgress<'a>, _: &()) -> Ordering {
2888        match self {
2889            TraversalTarget::Path(path) => path.cmp(&cursor_location.max_path),
2890            TraversalTarget::PathSuccessor(path) => {
2891                if !cursor_location.max_path.starts_with(path) {
2892                    Ordering::Equal
2893                } else {
2894                    Ordering::Greater
2895                }
2896            }
2897            TraversalTarget::Count {
2898                count,
2899                include_dirs,
2900                include_ignored,
2901            } => Ord::cmp(
2902                count,
2903                &cursor_location.count(*include_dirs, *include_ignored),
2904            ),
2905        }
2906    }
2907}
2908
2909struct ChildEntriesIter<'a> {
2910    parent_path: &'a Path,
2911    traversal: Traversal<'a>,
2912}
2913
2914impl<'a> Iterator for ChildEntriesIter<'a> {
2915    type Item = &'a Entry;
2916
2917    fn next(&mut self) -> Option<Self::Item> {
2918        if let Some(item) = self.traversal.entry() {
2919            if item.path.starts_with(&self.parent_path) {
2920                self.traversal.advance_to_sibling();
2921                return Some(item);
2922            }
2923        }
2924        None
2925    }
2926}
2927
2928impl<'a> From<&'a Entry> for proto::Entry {
2929    fn from(entry: &'a Entry) -> Self {
2930        Self {
2931            id: entry.id as u64,
2932            is_dir: entry.is_dir(),
2933            path: entry.path.to_string_lossy().to_string(),
2934            inode: entry.inode,
2935            mtime: Some(entry.mtime.into()),
2936            is_symlink: entry.is_symlink,
2937            is_ignored: entry.is_ignored,
2938        }
2939    }
2940}
2941
2942impl<'a> TryFrom<(&'a CharBag, proto::Entry)> for Entry {
2943    type Error = anyhow::Error;
2944
2945    fn try_from((root_char_bag, entry): (&'a CharBag, proto::Entry)) -> Result<Self> {
2946        if let Some(mtime) = entry.mtime {
2947            let kind = if entry.is_dir {
2948                EntryKind::Dir
2949            } else {
2950                let mut char_bag = root_char_bag.clone();
2951                char_bag.extend(entry.path.chars().map(|c| c.to_ascii_lowercase()));
2952                EntryKind::File(char_bag)
2953            };
2954            let path: Arc<Path> = Arc::from(Path::new(&entry.path));
2955            Ok(Entry {
2956                id: entry.id as usize,
2957                kind,
2958                path: path.clone(),
2959                inode: entry.inode,
2960                mtime: mtime.into(),
2961                is_symlink: entry.is_symlink,
2962                is_ignored: entry.is_ignored,
2963            })
2964        } else {
2965            Err(anyhow!(
2966                "missing mtime in remote worktree entry {:?}",
2967                entry.path
2968            ))
2969        }
2970    }
2971}
2972
2973#[cfg(test)]
2974mod tests {
2975    use super::*;
2976    use crate::fs::FakeFs;
2977    use anyhow::Result;
2978    use buffer::Point;
2979    use client::test::FakeServer;
2980    use fs::RealFs;
2981    use language::{tree_sitter_rust, LanguageServerConfig};
2982    use language::{Diagnostic, LanguageConfig};
2983    use lsp::Url;
2984    use rand::prelude::*;
2985    use serde_json::json;
2986    use std::{cell::RefCell, rc::Rc};
2987    use std::{
2988        env,
2989        fmt::Write,
2990        time::{SystemTime, UNIX_EPOCH},
2991    };
2992    use util::test::temp_tree;
2993
2994    #[gpui::test]
2995    async fn test_traversal(cx: gpui::TestAppContext) {
2996        let fs = FakeFs::new();
2997        fs.insert_tree(
2998            "/root",
2999            json!({
3000               ".gitignore": "a/b\n",
3001               "a": {
3002                   "b": "",
3003                   "c": "",
3004               }
3005            }),
3006        )
3007        .await;
3008
3009        let tree = Worktree::open_local(
3010            Client::new(),
3011            Arc::from(Path::new("/root")),
3012            Arc::new(fs),
3013            Default::default(),
3014            &mut cx.to_async(),
3015        )
3016        .await
3017        .unwrap();
3018        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3019            .await;
3020
3021        tree.read_with(&cx, |tree, _| {
3022            assert_eq!(
3023                tree.entries(false)
3024                    .map(|entry| entry.path.as_ref())
3025                    .collect::<Vec<_>>(),
3026                vec![
3027                    Path::new(""),
3028                    Path::new(".gitignore"),
3029                    Path::new("a"),
3030                    Path::new("a/c"),
3031                ]
3032            );
3033        })
3034    }
3035
3036    #[gpui::test]
3037    async fn test_save_file(mut cx: gpui::TestAppContext) {
3038        let dir = temp_tree(json!({
3039            "file1": "the old contents",
3040        }));
3041        let tree = Worktree::open_local(
3042            Client::new(),
3043            dir.path(),
3044            Arc::new(RealFs),
3045            Default::default(),
3046            &mut cx.to_async(),
3047        )
3048        .await
3049        .unwrap();
3050        let buffer = tree
3051            .update(&mut cx, |tree, cx| tree.open_buffer("file1", cx))
3052            .await
3053            .unwrap();
3054        let save = buffer.update(&mut cx, |buffer, cx| {
3055            buffer.edit(Some(0..0), "a line of text.\n".repeat(10 * 1024), cx);
3056            buffer.save(cx).unwrap()
3057        });
3058        save.await.unwrap();
3059
3060        let new_text = std::fs::read_to_string(dir.path().join("file1")).unwrap();
3061        assert_eq!(new_text, buffer.read_with(&cx, |buffer, _| buffer.text()));
3062    }
3063
3064    #[gpui::test]
3065    async fn test_save_in_single_file_worktree(mut cx: gpui::TestAppContext) {
3066        let dir = temp_tree(json!({
3067            "file1": "the old contents",
3068        }));
3069        let file_path = dir.path().join("file1");
3070
3071        let tree = Worktree::open_local(
3072            Client::new(),
3073            file_path.clone(),
3074            Arc::new(RealFs),
3075            Default::default(),
3076            &mut cx.to_async(),
3077        )
3078        .await
3079        .unwrap();
3080        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3081            .await;
3082        cx.read(|cx| assert_eq!(tree.read(cx).file_count(), 1));
3083
3084        let buffer = tree
3085            .update(&mut cx, |tree, cx| tree.open_buffer("", cx))
3086            .await
3087            .unwrap();
3088        let save = buffer.update(&mut cx, |buffer, cx| {
3089            buffer.edit(Some(0..0), "a line of text.\n".repeat(10 * 1024), cx);
3090            buffer.save(cx).unwrap()
3091        });
3092        save.await.unwrap();
3093
3094        let new_text = std::fs::read_to_string(file_path).unwrap();
3095        assert_eq!(new_text, buffer.read_with(&cx, |buffer, _| buffer.text()));
3096    }
3097
3098    #[gpui::test]
3099    async fn test_rescan_and_remote_updates(mut cx: gpui::TestAppContext) {
3100        let dir = temp_tree(json!({
3101            "a": {
3102                "file1": "",
3103                "file2": "",
3104                "file3": "",
3105            },
3106            "b": {
3107                "c": {
3108                    "file4": "",
3109                    "file5": "",
3110                }
3111            }
3112        }));
3113
3114        let user_id = 5;
3115        let mut client = Client::new();
3116        let server = FakeServer::for_client(user_id, &mut client, &cx).await;
3117        let tree = Worktree::open_local(
3118            client,
3119            dir.path(),
3120            Arc::new(RealFs),
3121            Default::default(),
3122            &mut cx.to_async(),
3123        )
3124        .await
3125        .unwrap();
3126
3127        let buffer_for_path = |path: &'static str, cx: &mut gpui::TestAppContext| {
3128            let buffer = tree.update(cx, |tree, cx| tree.open_buffer(path, cx));
3129            async move { buffer.await.unwrap() }
3130        };
3131        let id_for_path = |path: &'static str, cx: &gpui::TestAppContext| {
3132            tree.read_with(cx, |tree, _| {
3133                tree.entry_for_path(path)
3134                    .expect(&format!("no entry for path {}", path))
3135                    .id
3136            })
3137        };
3138
3139        let buffer2 = buffer_for_path("a/file2", &mut cx).await;
3140        let buffer3 = buffer_for_path("a/file3", &mut cx).await;
3141        let buffer4 = buffer_for_path("b/c/file4", &mut cx).await;
3142        let buffer5 = buffer_for_path("b/c/file5", &mut cx).await;
3143
3144        let file2_id = id_for_path("a/file2", &cx);
3145        let file3_id = id_for_path("a/file3", &cx);
3146        let file4_id = id_for_path("b/c/file4", &cx);
3147
3148        // Wait for the initial scan.
3149        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3150            .await;
3151
3152        // Create a remote copy of this worktree.
3153        let initial_snapshot = tree.read_with(&cx, |tree, _| tree.snapshot());
3154        let worktree_id = 1;
3155        let share_request = tree.update(&mut cx, |tree, cx| {
3156            tree.as_local().unwrap().share_request(cx)
3157        });
3158        let open_worktree = server.receive::<proto::OpenWorktree>().await.unwrap();
3159        server
3160            .respond(
3161                open_worktree.receipt(),
3162                proto::OpenWorktreeResponse { worktree_id: 1 },
3163            )
3164            .await;
3165
3166        let remote = Worktree::remote(
3167            proto::JoinWorktreeResponse {
3168                worktree: share_request.await.unwrap().worktree,
3169                replica_id: 1,
3170                peers: Vec::new(),
3171            },
3172            Client::new(),
3173            Default::default(),
3174            &mut cx.to_async(),
3175        )
3176        .await
3177        .unwrap();
3178
3179        cx.read(|cx| {
3180            assert!(!buffer2.read(cx).is_dirty());
3181            assert!(!buffer3.read(cx).is_dirty());
3182            assert!(!buffer4.read(cx).is_dirty());
3183            assert!(!buffer5.read(cx).is_dirty());
3184        });
3185
3186        // Rename and delete files and directories.
3187        tree.flush_fs_events(&cx).await;
3188        std::fs::rename(dir.path().join("a/file3"), dir.path().join("b/c/file3")).unwrap();
3189        std::fs::remove_file(dir.path().join("b/c/file5")).unwrap();
3190        std::fs::rename(dir.path().join("b/c"), dir.path().join("d")).unwrap();
3191        std::fs::rename(dir.path().join("a/file2"), dir.path().join("a/file2.new")).unwrap();
3192        tree.flush_fs_events(&cx).await;
3193
3194        let expected_paths = vec![
3195            "a",
3196            "a/file1",
3197            "a/file2.new",
3198            "b",
3199            "d",
3200            "d/file3",
3201            "d/file4",
3202        ];
3203
3204        cx.read(|app| {
3205            assert_eq!(
3206                tree.read(app)
3207                    .paths()
3208                    .map(|p| p.to_str().unwrap())
3209                    .collect::<Vec<_>>(),
3210                expected_paths
3211            );
3212
3213            assert_eq!(id_for_path("a/file2.new", &cx), file2_id);
3214            assert_eq!(id_for_path("d/file3", &cx), file3_id);
3215            assert_eq!(id_for_path("d/file4", &cx), file4_id);
3216
3217            assert_eq!(
3218                buffer2.read(app).file().unwrap().path().as_ref(),
3219                Path::new("a/file2.new")
3220            );
3221            assert_eq!(
3222                buffer3.read(app).file().unwrap().path().as_ref(),
3223                Path::new("d/file3")
3224            );
3225            assert_eq!(
3226                buffer4.read(app).file().unwrap().path().as_ref(),
3227                Path::new("d/file4")
3228            );
3229            assert_eq!(
3230                buffer5.read(app).file().unwrap().path().as_ref(),
3231                Path::new("b/c/file5")
3232            );
3233
3234            assert!(!buffer2.read(app).file().unwrap().is_deleted());
3235            assert!(!buffer3.read(app).file().unwrap().is_deleted());
3236            assert!(!buffer4.read(app).file().unwrap().is_deleted());
3237            assert!(buffer5.read(app).file().unwrap().is_deleted());
3238        });
3239
3240        // Update the remote worktree. Check that it becomes consistent with the
3241        // local worktree.
3242        remote.update(&mut cx, |remote, cx| {
3243            let update_message =
3244                tree.read(cx)
3245                    .snapshot()
3246                    .build_update(&initial_snapshot, worktree_id, true);
3247            remote
3248                .as_remote_mut()
3249                .unwrap()
3250                .snapshot
3251                .apply_update(update_message)
3252                .unwrap();
3253
3254            assert_eq!(
3255                remote
3256                    .paths()
3257                    .map(|p| p.to_str().unwrap())
3258                    .collect::<Vec<_>>(),
3259                expected_paths
3260            );
3261        });
3262    }
3263
3264    #[gpui::test]
3265    async fn test_rescan_with_gitignore(cx: gpui::TestAppContext) {
3266        let dir = temp_tree(json!({
3267            ".git": {},
3268            ".gitignore": "ignored-dir\n",
3269            "tracked-dir": {
3270                "tracked-file1": "tracked contents",
3271            },
3272            "ignored-dir": {
3273                "ignored-file1": "ignored contents",
3274            }
3275        }));
3276
3277        let tree = Worktree::open_local(
3278            Client::new(),
3279            dir.path(),
3280            Arc::new(RealFs),
3281            Default::default(),
3282            &mut cx.to_async(),
3283        )
3284        .await
3285        .unwrap();
3286        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3287            .await;
3288        tree.flush_fs_events(&cx).await;
3289        cx.read(|cx| {
3290            let tree = tree.read(cx);
3291            let tracked = tree.entry_for_path("tracked-dir/tracked-file1").unwrap();
3292            let ignored = tree.entry_for_path("ignored-dir/ignored-file1").unwrap();
3293            assert_eq!(tracked.is_ignored, false);
3294            assert_eq!(ignored.is_ignored, true);
3295        });
3296
3297        std::fs::write(dir.path().join("tracked-dir/tracked-file2"), "").unwrap();
3298        std::fs::write(dir.path().join("ignored-dir/ignored-file2"), "").unwrap();
3299        tree.flush_fs_events(&cx).await;
3300        cx.read(|cx| {
3301            let tree = tree.read(cx);
3302            let dot_git = tree.entry_for_path(".git").unwrap();
3303            let tracked = tree.entry_for_path("tracked-dir/tracked-file2").unwrap();
3304            let ignored = tree.entry_for_path("ignored-dir/ignored-file2").unwrap();
3305            assert_eq!(tracked.is_ignored, false);
3306            assert_eq!(ignored.is_ignored, true);
3307            assert_eq!(dot_git.is_ignored, true);
3308        });
3309    }
3310
3311    #[gpui::test]
3312    async fn test_open_and_share_worktree(mut cx: gpui::TestAppContext) {
3313        let user_id = 100;
3314        let mut client = Client::new();
3315        let server = FakeServer::for_client(user_id, &mut client, &cx).await;
3316
3317        let fs = Arc::new(FakeFs::new());
3318        fs.insert_tree(
3319            "/path",
3320            json!({
3321                "to": {
3322                    "the-dir": {
3323                        ".zed.toml": r#"collaborators = ["friend-1", "friend-2"]"#,
3324                        "a.txt": "a-contents",
3325                    },
3326                },
3327            }),
3328        )
3329        .await;
3330
3331        let worktree = Worktree::open_local(
3332            client.clone(),
3333            "/path/to/the-dir".as_ref(),
3334            fs,
3335            Default::default(),
3336            &mut cx.to_async(),
3337        )
3338        .await
3339        .unwrap();
3340
3341        {
3342            let cx = cx.to_async();
3343            client.authenticate_and_connect(&cx).await.unwrap();
3344        }
3345
3346        let open_worktree = server.receive::<proto::OpenWorktree>().await.unwrap();
3347        assert_eq!(
3348            open_worktree.payload,
3349            proto::OpenWorktree {
3350                root_name: "the-dir".to_string(),
3351                authorized_logins: vec!["friend-1".to_string(), "friend-2".to_string()],
3352            }
3353        );
3354
3355        server
3356            .respond(
3357                open_worktree.receipt(),
3358                proto::OpenWorktreeResponse { worktree_id: 5 },
3359            )
3360            .await;
3361        let remote_id = worktree
3362            .update(&mut cx, |tree, _| tree.as_local().unwrap().next_remote_id())
3363            .await;
3364        assert_eq!(remote_id, Some(5));
3365
3366        cx.update(move |_| drop(worktree));
3367        server.receive::<proto::CloseWorktree>().await.unwrap();
3368    }
3369
3370    #[gpui::test]
3371    async fn test_buffer_is_dirty(mut cx: gpui::TestAppContext) {
3372        use std::fs;
3373
3374        let dir = temp_tree(json!({
3375            "file1": "abc",
3376            "file2": "def",
3377            "file3": "ghi",
3378        }));
3379        let tree = Worktree::open_local(
3380            Client::new(),
3381            dir.path(),
3382            Arc::new(RealFs),
3383            Default::default(),
3384            &mut cx.to_async(),
3385        )
3386        .await
3387        .unwrap();
3388        tree.flush_fs_events(&cx).await;
3389        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3390            .await;
3391
3392        let buffer1 = tree
3393            .update(&mut cx, |tree, cx| tree.open_buffer("file1", cx))
3394            .await
3395            .unwrap();
3396        let events = Rc::new(RefCell::new(Vec::new()));
3397
3398        // initially, the buffer isn't dirty.
3399        buffer1.update(&mut cx, |buffer, cx| {
3400            cx.subscribe(&buffer1, {
3401                let events = events.clone();
3402                move |_, _, event, _| events.borrow_mut().push(event.clone())
3403            })
3404            .detach();
3405
3406            assert!(!buffer.is_dirty());
3407            assert!(events.borrow().is_empty());
3408
3409            buffer.edit(vec![1..2], "", cx);
3410        });
3411
3412        // after the first edit, the buffer is dirty, and emits a dirtied event.
3413        buffer1.update(&mut cx, |buffer, cx| {
3414            assert!(buffer.text() == "ac");
3415            assert!(buffer.is_dirty());
3416            assert_eq!(
3417                *events.borrow(),
3418                &[language::Event::Edited, language::Event::Dirtied]
3419            );
3420            events.borrow_mut().clear();
3421            buffer.did_save(buffer.version(), buffer.file().unwrap().mtime(), None, cx);
3422        });
3423
3424        // after saving, the buffer is not dirty, and emits a saved event.
3425        buffer1.update(&mut cx, |buffer, cx| {
3426            assert!(!buffer.is_dirty());
3427            assert_eq!(*events.borrow(), &[language::Event::Saved]);
3428            events.borrow_mut().clear();
3429
3430            buffer.edit(vec![1..1], "B", cx);
3431            buffer.edit(vec![2..2], "D", cx);
3432        });
3433
3434        // after editing again, the buffer is dirty, and emits another dirty event.
3435        buffer1.update(&mut cx, |buffer, cx| {
3436            assert!(buffer.text() == "aBDc");
3437            assert!(buffer.is_dirty());
3438            assert_eq!(
3439                *events.borrow(),
3440                &[
3441                    language::Event::Edited,
3442                    language::Event::Dirtied,
3443                    language::Event::Edited
3444                ],
3445            );
3446            events.borrow_mut().clear();
3447
3448            // TODO - currently, after restoring the buffer to its
3449            // previously-saved state, the is still considered dirty.
3450            buffer.edit(vec![1..3], "", cx);
3451            assert!(buffer.text() == "ac");
3452            assert!(buffer.is_dirty());
3453        });
3454
3455        assert_eq!(*events.borrow(), &[language::Event::Edited]);
3456
3457        // When a file is deleted, the buffer is considered dirty.
3458        let events = Rc::new(RefCell::new(Vec::new()));
3459        let buffer2 = tree
3460            .update(&mut cx, |tree, cx| tree.open_buffer("file2", cx))
3461            .await
3462            .unwrap();
3463        buffer2.update(&mut cx, |_, cx| {
3464            cx.subscribe(&buffer2, {
3465                let events = events.clone();
3466                move |_, _, event, _| events.borrow_mut().push(event.clone())
3467            })
3468            .detach();
3469        });
3470
3471        fs::remove_file(dir.path().join("file2")).unwrap();
3472        buffer2.condition(&cx, |b, _| b.is_dirty()).await;
3473        assert_eq!(
3474            *events.borrow(),
3475            &[language::Event::Dirtied, language::Event::FileHandleChanged]
3476        );
3477
3478        // When a file is already dirty when deleted, we don't emit a Dirtied event.
3479        let events = Rc::new(RefCell::new(Vec::new()));
3480        let buffer3 = tree
3481            .update(&mut cx, |tree, cx| tree.open_buffer("file3", cx))
3482            .await
3483            .unwrap();
3484        buffer3.update(&mut cx, |_, cx| {
3485            cx.subscribe(&buffer3, {
3486                let events = events.clone();
3487                move |_, _, event, _| events.borrow_mut().push(event.clone())
3488            })
3489            .detach();
3490        });
3491
3492        tree.flush_fs_events(&cx).await;
3493        buffer3.update(&mut cx, |buffer, cx| {
3494            buffer.edit(Some(0..0), "x", cx);
3495        });
3496        events.borrow_mut().clear();
3497        fs::remove_file(dir.path().join("file3")).unwrap();
3498        buffer3
3499            .condition(&cx, |_, _| !events.borrow().is_empty())
3500            .await;
3501        assert_eq!(*events.borrow(), &[language::Event::FileHandleChanged]);
3502        cx.read(|cx| assert!(buffer3.read(cx).is_dirty()));
3503    }
3504
3505    #[gpui::test]
3506    async fn test_buffer_file_changes_on_disk(mut cx: gpui::TestAppContext) {
3507        use buffer::{Point, Selection, SelectionGoal};
3508        use std::fs;
3509
3510        let initial_contents = "aaa\nbbbbb\nc\n";
3511        let dir = temp_tree(json!({ "the-file": initial_contents }));
3512        let tree = Worktree::open_local(
3513            Client::new(),
3514            dir.path(),
3515            Arc::new(RealFs),
3516            Default::default(),
3517            &mut cx.to_async(),
3518        )
3519        .await
3520        .unwrap();
3521        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3522            .await;
3523
3524        let abs_path = dir.path().join("the-file");
3525        let buffer = tree
3526            .update(&mut cx, |tree, cx| {
3527                tree.open_buffer(Path::new("the-file"), cx)
3528            })
3529            .await
3530            .unwrap();
3531
3532        // Add a cursor on each row.
3533        let selection_set_id = buffer.update(&mut cx, |buffer, cx| {
3534            assert!(!buffer.is_dirty());
3535            buffer.add_selection_set(
3536                &(0..3)
3537                    .map(|row| Selection {
3538                        id: row as usize,
3539                        start: Point::new(row, 1),
3540                        end: Point::new(row, 1),
3541                        reversed: false,
3542                        goal: SelectionGoal::None,
3543                    })
3544                    .collect::<Vec<_>>(),
3545                cx,
3546            )
3547        });
3548
3549        // Change the file on disk, adding two new lines of text, and removing
3550        // one line.
3551        buffer.read_with(&cx, |buffer, _| {
3552            assert!(!buffer.is_dirty());
3553            assert!(!buffer.has_conflict());
3554        });
3555        let new_contents = "AAAA\naaa\nBB\nbbbbb\n";
3556        fs::write(&abs_path, new_contents).unwrap();
3557
3558        // Because the buffer was not modified, it is reloaded from disk. Its
3559        // contents are edited according to the diff between the old and new
3560        // file contents.
3561        buffer
3562            .condition(&cx, |buffer, _| buffer.text() == new_contents)
3563            .await;
3564
3565        buffer.update(&mut cx, |buffer, _| {
3566            assert_eq!(buffer.text(), new_contents);
3567            assert!(!buffer.is_dirty());
3568            assert!(!buffer.has_conflict());
3569
3570            let cursor_positions = buffer
3571                .selection_set(selection_set_id)
3572                .unwrap()
3573                .selections::<Point, _>(&*buffer)
3574                .map(|selection| {
3575                    assert_eq!(selection.start, selection.end);
3576                    selection.start
3577                })
3578                .collect::<Vec<_>>();
3579            assert_eq!(
3580                cursor_positions,
3581                [Point::new(1, 1), Point::new(3, 1), Point::new(4, 0)]
3582            );
3583        });
3584
3585        // Modify the buffer
3586        buffer.update(&mut cx, |buffer, cx| {
3587            buffer.edit(vec![0..0], " ", cx);
3588            assert!(buffer.is_dirty());
3589            assert!(!buffer.has_conflict());
3590        });
3591
3592        // Change the file on disk again, adding blank lines to the beginning.
3593        fs::write(&abs_path, "\n\n\nAAAA\naaa\nBB\nbbbbb\n").unwrap();
3594
3595        // Because the buffer is modified, it doesn't reload from disk, but is
3596        // marked as having a conflict.
3597        buffer
3598            .condition(&cx, |buffer, _| buffer.has_conflict())
3599            .await;
3600    }
3601
3602    #[gpui::test]
3603    async fn test_language_server_diagnostics(mut cx: gpui::TestAppContext) {
3604        let (language_server_config, mut fake_server) =
3605            LanguageServerConfig::fake(cx.background()).await;
3606        let mut languages = LanguageRegistry::new();
3607        languages.add(Arc::new(Language::new(
3608            LanguageConfig {
3609                name: "Rust".to_string(),
3610                path_suffixes: vec!["rs".to_string()],
3611                language_server: Some(language_server_config),
3612                ..Default::default()
3613            },
3614            tree_sitter_rust::language(),
3615        )));
3616
3617        let dir = temp_tree(json!({
3618            "a.rs": "fn a() { A }",
3619            "b.rs": "const y: i32 = 1",
3620        }));
3621
3622        let tree = Worktree::open_local(
3623            Client::new(),
3624            dir.path(),
3625            Arc::new(RealFs),
3626            Arc::new(languages),
3627            &mut cx.to_async(),
3628        )
3629        .await
3630        .unwrap();
3631        cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
3632            .await;
3633
3634        // Cause worktree to start the fake language server
3635        let _buffer = tree
3636            .update(&mut cx, |tree, cx| tree.open_buffer("b.rs", cx))
3637            .await
3638            .unwrap();
3639
3640        fake_server
3641            .notify::<lsp::notification::PublishDiagnostics>(lsp::PublishDiagnosticsParams {
3642                uri: Url::from_file_path(dir.path().join("a.rs")).unwrap(),
3643                version: None,
3644                diagnostics: vec![lsp::Diagnostic {
3645                    range: lsp::Range::new(lsp::Position::new(0, 9), lsp::Position::new(0, 10)),
3646                    severity: Some(lsp::DiagnosticSeverity::ERROR),
3647                    message: "undefined variable 'A'".to_string(),
3648                    ..Default::default()
3649                }],
3650            })
3651            .await;
3652
3653        let buffer = tree
3654            .update(&mut cx, |tree, cx| tree.open_buffer("a.rs", cx))
3655            .await
3656            .unwrap();
3657
3658        buffer.read_with(&cx, |buffer, _| {
3659            let diagnostics = buffer
3660                .diagnostics_in_range(0..buffer.len())
3661                .collect::<Vec<_>>();
3662            assert_eq!(
3663                diagnostics,
3664                &[(
3665                    Point::new(0, 9)..Point::new(0, 10),
3666                    &Diagnostic {
3667                        severity: lsp::DiagnosticSeverity::ERROR,
3668                        message: "undefined variable 'A'".to_string(),
3669                        group_id: 0,
3670                        is_primary: true
3671                    }
3672                )]
3673            )
3674        });
3675    }
3676
3677    #[gpui::test(iterations = 100)]
3678    fn test_random(mut rng: StdRng) {
3679        let operations = env::var("OPERATIONS")
3680            .map(|o| o.parse().unwrap())
3681            .unwrap_or(40);
3682        let initial_entries = env::var("INITIAL_ENTRIES")
3683            .map(|o| o.parse().unwrap())
3684            .unwrap_or(20);
3685
3686        let root_dir = tempdir::TempDir::new("worktree-test").unwrap();
3687        for _ in 0..initial_entries {
3688            randomly_mutate_tree(root_dir.path(), 1.0, &mut rng).unwrap();
3689        }
3690        log::info!("Generated initial tree");
3691
3692        let (notify_tx, _notify_rx) = smol::channel::unbounded();
3693        let fs = Arc::new(RealFs);
3694        let next_entry_id = Arc::new(AtomicUsize::new(0));
3695        let mut initial_snapshot = Snapshot {
3696            id: 0,
3697            scan_id: 0,
3698            abs_path: root_dir.path().into(),
3699            entries_by_path: Default::default(),
3700            entries_by_id: Default::default(),
3701            removed_entry_ids: Default::default(),
3702            ignores: Default::default(),
3703            root_name: Default::default(),
3704            root_char_bag: Default::default(),
3705            next_entry_id: next_entry_id.clone(),
3706        };
3707        initial_snapshot.insert_entry(
3708            Entry::new(
3709                Path::new("").into(),
3710                &smol::block_on(fs.metadata(root_dir.path()))
3711                    .unwrap()
3712                    .unwrap(),
3713                &next_entry_id,
3714                Default::default(),
3715            ),
3716            fs.as_ref(),
3717        );
3718        let mut scanner = BackgroundScanner::new(
3719            Arc::new(Mutex::new(initial_snapshot.clone())),
3720            notify_tx,
3721            fs.clone(),
3722            Arc::new(gpui::executor::Background::new()),
3723        );
3724        smol::block_on(scanner.scan_dirs()).unwrap();
3725        scanner.snapshot().check_invariants();
3726
3727        let mut events = Vec::new();
3728        let mut snapshots = Vec::new();
3729        let mut mutations_len = operations;
3730        while mutations_len > 1 {
3731            if !events.is_empty() && rng.gen_bool(0.4) {
3732                let len = rng.gen_range(0..=events.len());
3733                let to_deliver = events.drain(0..len).collect::<Vec<_>>();
3734                log::info!("Delivering events: {:#?}", to_deliver);
3735                smol::block_on(scanner.process_events(to_deliver));
3736                scanner.snapshot().check_invariants();
3737            } else {
3738                events.extend(randomly_mutate_tree(root_dir.path(), 0.6, &mut rng).unwrap());
3739                mutations_len -= 1;
3740            }
3741
3742            if rng.gen_bool(0.2) {
3743                snapshots.push(scanner.snapshot());
3744            }
3745        }
3746        log::info!("Quiescing: {:#?}", events);
3747        smol::block_on(scanner.process_events(events));
3748        scanner.snapshot().check_invariants();
3749
3750        let (notify_tx, _notify_rx) = smol::channel::unbounded();
3751        let mut new_scanner = BackgroundScanner::new(
3752            Arc::new(Mutex::new(initial_snapshot)),
3753            notify_tx,
3754            scanner.fs.clone(),
3755            scanner.executor.clone(),
3756        );
3757        smol::block_on(new_scanner.scan_dirs()).unwrap();
3758        assert_eq!(
3759            scanner.snapshot().to_vec(true),
3760            new_scanner.snapshot().to_vec(true)
3761        );
3762
3763        for mut prev_snapshot in snapshots {
3764            let include_ignored = rng.gen::<bool>();
3765            if !include_ignored {
3766                let mut entries_by_path_edits = Vec::new();
3767                let mut entries_by_id_edits = Vec::new();
3768                for entry in prev_snapshot
3769                    .entries_by_id
3770                    .cursor::<()>()
3771                    .filter(|e| e.is_ignored)
3772                {
3773                    entries_by_path_edits.push(Edit::Remove(PathKey(entry.path.clone())));
3774                    entries_by_id_edits.push(Edit::Remove(entry.id));
3775                }
3776
3777                prev_snapshot
3778                    .entries_by_path
3779                    .edit(entries_by_path_edits, &());
3780                prev_snapshot.entries_by_id.edit(entries_by_id_edits, &());
3781            }
3782
3783            let update = scanner
3784                .snapshot()
3785                .build_update(&prev_snapshot, 0, include_ignored);
3786            prev_snapshot.apply_update(update).unwrap();
3787            assert_eq!(
3788                prev_snapshot.to_vec(true),
3789                scanner.snapshot().to_vec(include_ignored)
3790            );
3791        }
3792    }
3793
3794    fn randomly_mutate_tree(
3795        root_path: &Path,
3796        insertion_probability: f64,
3797        rng: &mut impl Rng,
3798    ) -> Result<Vec<fsevent::Event>> {
3799        let root_path = root_path.canonicalize().unwrap();
3800        let (dirs, files) = read_dir_recursive(root_path.clone());
3801
3802        let mut events = Vec::new();
3803        let mut record_event = |path: PathBuf| {
3804            events.push(fsevent::Event {
3805                event_id: SystemTime::now()
3806                    .duration_since(UNIX_EPOCH)
3807                    .unwrap()
3808                    .as_secs(),
3809                flags: fsevent::StreamFlags::empty(),
3810                path,
3811            });
3812        };
3813
3814        if (files.is_empty() && dirs.len() == 1) || rng.gen_bool(insertion_probability) {
3815            let path = dirs.choose(rng).unwrap();
3816            let new_path = path.join(gen_name(rng));
3817
3818            if rng.gen() {
3819                log::info!("Creating dir {:?}", new_path.strip_prefix(root_path)?);
3820                std::fs::create_dir(&new_path)?;
3821            } else {
3822                log::info!("Creating file {:?}", new_path.strip_prefix(root_path)?);
3823                std::fs::write(&new_path, "")?;
3824            }
3825            record_event(new_path);
3826        } else if rng.gen_bool(0.05) {
3827            let ignore_dir_path = dirs.choose(rng).unwrap();
3828            let ignore_path = ignore_dir_path.join(&*GITIGNORE);
3829
3830            let (subdirs, subfiles) = read_dir_recursive(ignore_dir_path.clone());
3831            let files_to_ignore = {
3832                let len = rng.gen_range(0..=subfiles.len());
3833                subfiles.choose_multiple(rng, len)
3834            };
3835            let dirs_to_ignore = {
3836                let len = rng.gen_range(0..subdirs.len());
3837                subdirs.choose_multiple(rng, len)
3838            };
3839
3840            let mut ignore_contents = String::new();
3841            for path_to_ignore in files_to_ignore.chain(dirs_to_ignore) {
3842                write!(
3843                    ignore_contents,
3844                    "{}\n",
3845                    path_to_ignore
3846                        .strip_prefix(&ignore_dir_path)?
3847                        .to_str()
3848                        .unwrap()
3849                )
3850                .unwrap();
3851            }
3852            log::info!(
3853                "Creating {:?} with contents:\n{}",
3854                ignore_path.strip_prefix(&root_path)?,
3855                ignore_contents
3856            );
3857            std::fs::write(&ignore_path, ignore_contents).unwrap();
3858            record_event(ignore_path);
3859        } else {
3860            let old_path = {
3861                let file_path = files.choose(rng);
3862                let dir_path = dirs[1..].choose(rng);
3863                file_path.into_iter().chain(dir_path).choose(rng).unwrap()
3864            };
3865
3866            let is_rename = rng.gen();
3867            if is_rename {
3868                let new_path_parent = dirs
3869                    .iter()
3870                    .filter(|d| !d.starts_with(old_path))
3871                    .choose(rng)
3872                    .unwrap();
3873
3874                let overwrite_existing_dir =
3875                    !old_path.starts_with(&new_path_parent) && rng.gen_bool(0.3);
3876                let new_path = if overwrite_existing_dir {
3877                    std::fs::remove_dir_all(&new_path_parent).ok();
3878                    new_path_parent.to_path_buf()
3879                } else {
3880                    new_path_parent.join(gen_name(rng))
3881                };
3882
3883                log::info!(
3884                    "Renaming {:?} to {}{:?}",
3885                    old_path.strip_prefix(&root_path)?,
3886                    if overwrite_existing_dir {
3887                        "overwrite "
3888                    } else {
3889                        ""
3890                    },
3891                    new_path.strip_prefix(&root_path)?
3892                );
3893                std::fs::rename(&old_path, &new_path)?;
3894                record_event(old_path.clone());
3895                record_event(new_path);
3896            } else if old_path.is_dir() {
3897                let (dirs, files) = read_dir_recursive(old_path.clone());
3898
3899                log::info!("Deleting dir {:?}", old_path.strip_prefix(&root_path)?);
3900                std::fs::remove_dir_all(&old_path).unwrap();
3901                for file in files {
3902                    record_event(file);
3903                }
3904                for dir in dirs {
3905                    record_event(dir);
3906                }
3907            } else {
3908                log::info!("Deleting file {:?}", old_path.strip_prefix(&root_path)?);
3909                std::fs::remove_file(old_path).unwrap();
3910                record_event(old_path.clone());
3911            }
3912        }
3913
3914        Ok(events)
3915    }
3916
3917    fn read_dir_recursive(path: PathBuf) -> (Vec<PathBuf>, Vec<PathBuf>) {
3918        let child_entries = std::fs::read_dir(&path).unwrap();
3919        let mut dirs = vec![path];
3920        let mut files = Vec::new();
3921        for child_entry in child_entries {
3922            let child_path = child_entry.unwrap().path();
3923            if child_path.is_dir() {
3924                let (child_dirs, child_files) = read_dir_recursive(child_path);
3925                dirs.extend(child_dirs);
3926                files.extend(child_files);
3927            } else {
3928                files.push(child_path);
3929            }
3930        }
3931        (dirs, files)
3932    }
3933
3934    fn gen_name(rng: &mut impl Rng) -> String {
3935        (0..6)
3936            .map(|_| rng.sample(rand::distributions::Alphanumeric))
3937            .map(char::from)
3938            .collect()
3939    }
3940
3941    impl Snapshot {
3942        fn check_invariants(&self) {
3943            let mut files = self.files(true, 0);
3944            let mut visible_files = self.files(false, 0);
3945            for entry in self.entries_by_path.cursor::<()>() {
3946                if entry.is_file() {
3947                    assert_eq!(files.next().unwrap().inode, entry.inode);
3948                    if !entry.is_ignored {
3949                        assert_eq!(visible_files.next().unwrap().inode, entry.inode);
3950                    }
3951                }
3952            }
3953            assert!(files.next().is_none());
3954            assert!(visible_files.next().is_none());
3955
3956            let mut bfs_paths = Vec::new();
3957            let mut stack = vec![Path::new("")];
3958            while let Some(path) = stack.pop() {
3959                bfs_paths.push(path);
3960                let ix = stack.len();
3961                for child_entry in self.child_entries(path) {
3962                    stack.insert(ix, &child_entry.path);
3963                }
3964            }
3965
3966            let dfs_paths = self
3967                .entries_by_path
3968                .cursor::<()>()
3969                .map(|e| e.path.as_ref())
3970                .collect::<Vec<_>>();
3971            assert_eq!(bfs_paths, dfs_paths);
3972
3973            for (ignore_parent_path, _) in &self.ignores {
3974                assert!(self.entry_for_path(ignore_parent_path).is_some());
3975                assert!(self
3976                    .entry_for_path(ignore_parent_path.join(&*GITIGNORE))
3977                    .is_some());
3978            }
3979        }
3980
3981        fn to_vec(&self, include_ignored: bool) -> Vec<(&Path, u64, bool)> {
3982            let mut paths = Vec::new();
3983            for entry in self.entries_by_path.cursor::<()>() {
3984                if include_ignored || !entry.is_ignored {
3985                    paths.push((entry.path.as_ref(), entry.inode, entry.is_ignored));
3986                }
3987            }
3988            paths.sort_by(|a, b| a.0.cmp(&b.0));
3989            paths
3990        }
3991    }
3992}