This is a ~small~ pure refactor that's a step toward SSH remoting. I've
extracted the Project's buffer state management into a smaller, separate
struct called `BufferStore`, currently in the same crate. I did this as
a separate PR to reduce conflicts between main and `remoting-over-ssh`.
The idea is to make use of this struct (and other smaller structs that
make up `Project`) in a dedicated, simpler `HeadlessProject` type that
we will use in the SSH server to model the remote end of a project. With
this approach, as we develop the headless project, we can avoid adding
more conditional logic to `Project` itself (which is already very
complex), and actually make `Project` a bit smaller by extracting out
helper objects.
Release Notes:
- N/A
In some rare cases, we wouldn't pick up .gitignore files in the right
order, causing performance issues for the project search and the file
finder
Release Notes:
- N/A
I found this bug while investigating
https://github.com/zed-industries/zed/issues/13176. When running zed
with `RUST_LOG=worktree=trace`, I realized we were updating all
gitignore statuses on every file change. This was due to a logic error
where we were marking a gitignore as up-to-date on a temporary *clone*
of our snapshot, but not in the `BackgroundScanner` itself.
Release Notes:
- Fixed a bug that caused unnecessary computations to happen on every
file-system event.
This fixes#13316 by checking whether there are any local workspace
settings for a given file.
Release Notes:
- Fixed `autosave` settings in project-specific settings file being
ignored. ([#13316](https://github.com/zed-industries/zed/issues/13316)).
Co-authored-by: Bennet <bennet@zed.dev>
This fixes#4432 by ensuring that we scan & watch the `.zed` folder,
just like we watch the `.git`, for changes.
Release Notes:
- Settings are now loaded from local `.zed/settings.json` files even if
they are `.gitignore`d.
([#4432](https://github.com/zed-industries/zed/issues/4432)).
Co-authored-by: Bennet <bennet@zed.dev>
This PR replaces the `lazy_static!` usages in the `util` crate with
`OnceLock` from the standard library.
This allows us to drop the `lazy_static` dependency from this crate.
Release Notes:
- N/A
Previously we were using a single globset::Glob in PathMatcher; higher
up the stack, we were then resorting to using a list of PathMatchers.
globset crate exposes a GlobSet type that's better suited for this use
case. In my benchmarks, using a single PathMatcher with GlobSet instead
of a Vec of PathMatchers with Globs is about 3 times faster with the
default 'file_scan_exclusions' values. This slightly improves our
project load time for projects with large # of files, as showcased in
the following videos of loading a project with 100k source files. This
project is *not* a git repository, so it should measure raw overhead on
our side.
Current nightly: 51404d4ea0https://github.com/zed-industries/zed/assets/24362066/e0aa9f8c-aae6-4348-8d42-d20bd41fcd76
versus this PR:
https://github.com/zed-industries/zed/assets/24362066/408dcab1-cee2-4c9e-a541-a31d14772dd7
Release Notes:
- Improved performance in large worktrees
This fixes `project_tests::rescan_and_remote_updates` .
That test was actually correctly failing, revealing two bugs on Linux.
Release Notes:
- Fixed an issue where file renames were not detected on Linux.
- Fixed performance problems caused by excessive file system events on
Linux.
---------
Co-authored-by: Mikayla <mikayla@zed.dev>
It was possible to unload a root of worktree when it was a .git
directory; due to that, test_fs_events_in_dot_git_worktree was sometimes
stuck in an infinite loop on CI.
The gist of an issue is that when .git dir is a root dir, then modifying
a file within this directory could sometimes unload the .git dir; the
test went into an infinite loop when the first event in an filesystem
stream was not the event for the file creation, but for a dir
modification. In that case we'd unload the root directory and a
subsequent event for file creation would never be registered, leading to
the test being stuck waiting for it to happen.
This commit alleviates it by special-casing worktrees rooted in .git
directories.
Release Notes:
- Fixed a possible hang when opening a worktree in .git directory.
This PR is an internal refactor in preparation for remote editing. It
restructures the public interface of `Worktree`, reducing the number of
call sites that assume that a worktree is local or remote.
* The Project no longer calls `worktree.as_local_mut().unwrap()` in code
paths related to basic file operations
* Fewer code paths in the app rely on the worktree's `LocalSnapshot`
* Worktree-related RPC message handling is more fully encapsulated by
the `Worktree` type.
to do:
* [x] file manipulation operations
* [x] sending worktree updates when sharing
for later
* opening buffers
* updating open buffers upon worktree changes
Release Notes:
- N/A
The `worktree` crate mainly provides an in-memory model of a directory
and its git repositories. But because it was originally extracted from
the Project crate, it also contained lingering bits of code that were
outside of that area:
* it had a little bit of logic related to buffers (though most buffer
management lives in `project`)
* it had a *little* bit of logic for storing diagnostics (though the
vast majority of LSP and diagnostic logic lives in `project`)
* it had a little bit of logic for sending RPC message (though the
*receiving* logic for those RPC messages lived in `project`)
In this PR, I've moved those concerns entirely to the project crate
(where they were already dealt with for the most part), so that the
worktree crate can be more focused on its main job, and have fewer
dependencies.
Worktree no longer depends on `client` or `lsp`. It still depends on
`language`, but only because of `impl language::File for
worktree::File`.
Release Notes:
- N/A
Fixes https://github.com/zed-industries/zed/issues/10890
* removes `unwrap()` that caused panics for text elements with no text,
remaining after edit state is cleared but project entries are not
updated, having the fake, "new entry"
* improves discoverability of the FS errors during file/directory
creation: now those are shown as workspace notifications
* stops printing anyhow backtraces in workspace notifications, printing
the more readable chain of contexts instead
* better indicates when new entries are created as excluded ones
Release Notes:
- Improve excluded entry creation workflow in the project panel
([10890](https://github.com/zed-industries/zed/issues/10890))
Previously, each git `Repository` object was held inside of a mutex.
This was needed because libgit2's Repository object is (as one would
expect) not thread safe. But now, the two longest-running git operations
that Zed performs, (`status` and `blame`) do not use libgit2 - they
invoke the `git` executable. For these operations, it's not necessary to
hold a lock on the repository.
In this PR, I've moved our mutex usage so that it only wraps the libgit2
calls, not our `git` subprocess spawns. The main user-facing impact of
this is that the UI is much more responsive when initially opening a
project with a very large git repository (e.g. `chromium`, `webkit`,
`linux`).
Release Notes:
- Improved Zed's responsiveness when initially opening a project
containing a very large git repository.
I realized that somehow, the `git` executable is able to compute `git
status` much more quickly than libgit2, so I've switched our git status
logic to use `git`. Follow-up to
https://github.com/zed-industries/zed/pull/12266.
Release Notes:
- Improved the performance of git status updated when working in large
git repositories.
Fixes https://github.com/zed-industries/zed/issues/9575
Fixes https://github.com/zed-industries/zed/issues/4294
### Problem
When a large git repository's `.git` folder changes (due to a `git
commit`, `git reset` etc), Zed needs to recompute the git status for
every file in that git repository. Part of computing the git status is
the *unstaged* part - the comparison between the content of the file and
the version in the git index. In a large git repository like `chromium`
or `linux`, this is inherently pretty slow.
Previously, we performed this git status all at once, and held a lock on
our `BackgroundScanner`'s state for the entire time. On my laptop, in
the `linux` repo, this would often take around 13 seconds.
When opening a file, Zed always refreshes the metadata for that file in
its in-memory snapshot of worktree. This is normally very fast, but if
another task is holding a lock on the `BackgroundScanner`, it blocks.
### Solution
I've restructured how Zed handles Git statuses, so that when a git
repository is updated, we recompute files' git statuses in fixed-sized
batches. In between these batches, the `BackgroundScanner` is free to
perform other work, so that file operations coming from the main thread
will still be responsive.
Release Notes:
- Fixed a bug that caused long delays in opening files right after
performing a commit in very large git repositories.
In Windows platform, using notify to watch file events.
1. in [notify windows
implement](3df0f65152/notify/src/windows.rs (L344)),
we get the full file path, just with `path.join(file_path)`.
2. In [zed worktree
start_backgroud_scan_tasks](d2569afe66/crates/worktree/src/worktree.rs (L679)),
`abs_path` is not unc path, so we get all file events with not unc path.
3. but in [zed worktree
process_event](d2569afe66/crates/worktree/src/worktree.rs (L3619)),
we `strip_prefix` unc path all times, it will always print annoy error.
@mikayla-maki I can't reopen pre closed pr #10501 .
Release Notes:
- N/A
As an attempt to do things better when showing diff hunks, store diff
base as Rope, not String, to have cheaper clones when the diff base text
is reused, e.g. creating another buffer with the diff base text for hunk
diff expanding.
Release Notes:
- N/A
TODO:
- [x] Don't immediately seg fault
- [x] Implement for directories
- [x] Add cmd-delete to remove files
- [ ] ~~Add setting for trash vs. delete~~ You can just use keybindings
to change the behavior.
fixes https://github.com/zed-industries/zed/issues/7228
fixes https://github.com/zed-industries/zed/issues/5094
Release Notes:
- Added a new `project_panel::Trash` action and changed the default
behavior for `backspace` and `delete` in the project panel to send a
file to the systems trash, instead of permanently deleting it
([#7228](https://github.com/zed-industries/zed/issues/7228),
[#5094](https://github.com/zed-industries/zed/issues/5094)). The
original behavior can be restored by adding the following section to
your keybindings:
```json5
[
// ...Other keybindings...
{
"context": "ProjectPanel",
"bindings": {
"backspace": "project_panel::Delete",
"delete": "project_panel::Delete",
}
}
]
Still TODO:
* Disable the new save-as for local projects
* Wire up sending the new path to the remote server
Release Notes:
- Added the ability to "Save-as" in remote projects
---------
Co-authored-by: Nathan <nathan@zed.dev>
Co-authored-by: Bennet <bennetbo@gmx.de>
Fixed auto folded dirs which caused significant performance issues #8476
(#7674)
Moved from iterating over snapshot entries to use `child_entries`
function from `worktree.rs` by making it public
@maxbrunsfeld
Release Notes:
- Fixed a bug where project panel settings changes would not be applied
immediately.
- Added a `project_panel.auto_fold_dirs` setting which collapses the
nesting in the project panel when there is a chain of folders containing
a single folder.
<img width="288" alt="Screenshot 2024-04-12 at 11 10 58 AM"
src="https://github.com/zed-industries/zed/assets/2280405/efd61e75-026c-464d-ba4d-90db5f68bad3">
---------
Co-authored-by: Mikayla <mikayla@zed.dev>
This reverts commit caed275fbf.
NOTE: this should not be merged until #9668 is on stable and the
`ZedVersion#can_collaborate` is updated to exclude all clients without
that change.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This PR renames `language::Buffer::new` to `language::Buffer::local` and
simplifies its interface. Instead of taking a replica id (which should
always be 0 for the local case) and a `BufferId`, which was awkward and
verbose to construct, it simply takes text and a `cx`.
It uses the `cx` to derive a `BufferId` from the `EntityId` associated
with the `cx`, which should always be positive based on the following
analysis...
We convert the entity id to a u64 using this method on `EntityId`, which
is defined by macros in the `slotmap` crate:
```rust
pub fn as_ffi(self) -> u64 {
(u64::from(self.version.get()) << 32) | u64::from(self.idx)
}
```
If you look at the type of `version` in `KeyData`, it is non-zero:
```rust
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct KeyData {
idx: u32,
version: NonZeroU32,
}
```
This commit also adds `Context::reserve_model` and
`Context::insert_model` to determine a model's entity ID before it is
created, which we need in order to assign a `BufferId` in the background
when loading a buffer asynchronously.
Release Notes:
- N/A
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This PR adds the ability for extensions to provide certain language
settings via the language `config.toml`.
These settings are then merged in with the rest of the settings when the
language is loaded from the extension.
The language settings that are available are:
- `tab_size`
- `hard_tabs`
- `soft_wrap`
Additionally, for bundled languages we moved these settings out of the
`settings/default.json` and into their respective `config.toml`s .
For languages currently provided by extensions, we are leaving the
values in the `settings/default.json` temporarily until all released
versions of Zed are able to load these settings from the extension.
---
Along the way we ended up refactoring the `Settings::load` method
slightly, introducing a new `SettingsSources` struct to better convey
where the settings are being loaded from.
This makes it easier to load settings from specific locations/sets of
locations in an explicit way.
Release Notes:
- N/A
---------
Co-authored-by: Max <max@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Closes https://github.com/zed-industries/zed/issues/4730
![image](https://github.com/zed-industries/zed/assets/2690773/d3c5317f-8120-45b5-b57c-c0fb5d8c066d)
To the left is a symlink, to the right — the real file.
The issue was due to the fact, that symlinks files contain the file path
to the real file, and git (properly) treats that symlink file contents
as diff base, returning in `load_index_text` (via `let content =
repo.find_blob(oid)?.content().to_owned();`) the contents of that
symlink file — the path.
The fix checks for FS metadata before fetching the git diff base, and
skips it entirely for symlinks: Zed opens the symlink file contents
instead, fully obscuring the git symlink diff hunks.
Interesting, that VSCode behaves as Zed before the fix; while the fix
makes Zed behave like Intellij* IDEs now.
Release Notes:
- Fixed git diff hunks appearing in the symlinked files
([4730](https://github.com/zed-industries/zed/issues/4730))
This adds a new action to the editor: `editor: toggle git blame`. When
used it turns on a sidebar containing `git blame` information for the
currently open buffer.
The git blame information is updated when the buffer changes. It handles
additions, deletions, modifications, changes to the underlying git data
(new commits, changed commits, ...), file saves. It also handles folding
and wrapping lines correctly.
When the user hovers over a commit, a tooltip displays information for
the commit that introduced the line. If the repository has a remote with
the name `origin` configured, then clicking on a blame entry opens the
permalink to the commit on the code host.
Users can right-click on a blame entry to get a context menu which
allows them to copy the SHA of the commit.
The feature also works on shared projects, e.g. when collaborating a
peer can request `git blame` data.
As of this PR, Zed now comes bundled with a `git` binary so that users
don't have to have `git` installed locally to use this feature.
### Screenshots
![screenshot-2024-03-28-13 57
43@2x](https://github.com/zed-industries/zed/assets/1185253/ee8ec55d-3b5e-4d63-a85a-852da914f5ba)
![screenshot-2024-03-28-14 01
23@2x](https://github.com/zed-industries/zed/assets/1185253/2ba8efd7-e887-4076-a87a-587a732b9e9a)
![screenshot-2024-03-28-14 01
32@2x](https://github.com/zed-industries/zed/assets/1185253/496f4a06-b189-4881-b427-2289ae6e6075)
### TODOs
- [x] Bundling `git` binary
### Release Notes
Release Notes:
- Added `editor: toggle git blame` command that toggles a sidebar with
git blame information for the current buffer.
---------
Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Piotr <piotr@zed.dev>
Co-authored-by: Bennet <bennetbo@gmx.de>
Co-authored-by: Mikayla <mikayla@zed.dev>
This pull request introduces a new `InlineCompletionProvider` trait,
which enables making `Editor` copilot-agnostic and lets us push all the
copilot functionality into the `copilot_ui` module. Long-term, I would
like to merge `copilot` and `copilot_ui`, but right now `project`
depends on `copilot`, which makes this impossible.
The reason for adding this new trait is so that we can experiment with
other inline completion providers and swap them at runtime using config
settings.
Please, note also that we renamed some of the existing copilot actions
to be more agnostic (see release notes below). We still kept the old
actions bound for backwards-compatibility, but we should probably remove
them at some later version.
Also, as a drive-by, we added new methods to the `Global` trait that let
you read or mutate a global directly, e.g.:
```rs
MyGlobal::update(cx, |global, cx| {
});
```
Release Notes:
- Renamed the `copilot::Suggest` action to
`editor::ShowInlineCompletion`
- Renamed the `copilot::NextSuggestion` action to
`editor::NextInlineCompletion`
- Renamed the `copilot::PreviousSuggestion` action to
`editor::PreviousInlineCompletion`
- Renamed the `editor::AcceptPartialCopilotSuggestion` action to
`editor::AcceptPartialInlineCompletion`
---------
Co-authored-by: Nathan <nathan@zed.dev>
Co-authored-by: Kyle <kylek@zed.dev>
Co-authored-by: Kyle Kelley <rgbkrk@gmail.com>
This PR fixes file name coloring in the project panel and tabs when
.gitignore file is updated. It's intended to fix#7831.
There's another, less vivid, problem with git-aware labels coloring.
It's about files that are both ignored and contained in the git index.
I'll file a separate issue for it to keep this fix focused.
Release Notes:
- Fixed file Git status refreshing on .gitignore update (#7831).
Closes#5178
Release Notes:
- Added a `file_types` setting that can be used to associate languages
with file names and file extensions. For example, to interpret all `.c`
files as C++, and files called `MyLockFile` as TOML, add the following
to `settings.json`:
```json
{
"file_types": {
"C++": ["c"],
"TOML": ["MyLockFile"]
}
}
```
As with most zed settings, this can be configured on a per-directory
basis by including a local `.zed/settings.json` file in that directory.
---------
Co-authored-by: Marshall <marshall@zed.dev>