git_ui: Move git_graph into git_ui (#57503)
cc @Anthony-Eid ## Why This is the first step in moving the Git Graph work into the Git UI crate before continuing with follow-up refactors and feature work. The goal is for Git UI components and shared Git UI helpers to live in one crate, so future changes to the Git Graph can reuse existing `git_ui` code instead of duplicating it. This PR is not only a filesystem move. While moving `git_graph` into `git_ui`, a few small dependency and helper boundaries had to change: - `git_graph` and `git_ui` both needed the same remote parsing and commit tooltip construction behavior, so those pieces are now shared from `git_ui`. - `git_graph` previously depended on `project_panel` to resolve file-history actions from the project panel selection. After moving `git_graph` into `git_ui`, keeping that dependency would create an undesirable `git_ui` -> `project_panel` relationship. The project-panel-specific action forwarding now lives in `project_panel`, and calls into exported `git_ui::git_graph` helpers instead. - `git_graph` initialization now happens through `git_ui::init`, so downstream crates only need to initialize `git_ui`. This prepares the codebase for the next planned PRs: splitting the large `git_graph.rs` implementation into smaller pieces, then adding Git Graph features such as keeping the main branch lane at index `0`. ## License removal The removed `crates/git_graph/LICENSE-GPL` file was a symlink to the repository root `LICENSE-GPL`. The moved code is now inside `git_ui`, which is also licensed as `GPL-3.0-or-later` and has its own `LICENSE-GPL` symlink to the same root license file. The code did not move to a differently licensed crate; it remains covered by the same GPL license. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: Anthony Eid <anthony@zed.dev>
This commit is contained in:
1 parent
b369cc24b1
commit
9abfeab186
17 files changed
+451
-257
No files matched your search
Generated
+3
-36
@@ -3373,7 +3373,6 @@ dependencies = [
|
||||
"fs",
|
||||
"futures 0.3.32",
|
||||
"git",
|
||||
"git_graph",
|
||||
"git_hosting_providers",
|
||||
"git_ui",
|
||||
"gpui",
|
||||
@@ -7279,40 +7278,6 @@ dependencies = [
|
||||
"ztracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git_graph"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel 2.5.0",
|
||||
"collections",
|
||||
"db",
|
||||
"editor",
|
||||
"fs",
|
||||
"git",
|
||||
"git_ui",
|
||||
"gpui",
|
||||
"language",
|
||||
"language_model",
|
||||
"menu",
|
||||
"picker",
|
||||
"project",
|
||||
"project_panel",
|
||||
"rand 0.9.4",
|
||||
"release_channel",
|
||||
"remote_connection",
|
||||
"search",
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smallvec",
|
||||
"task",
|
||||
"theme",
|
||||
"theme_settings",
|
||||
"time",
|
||||
"ui",
|
||||
"workspace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git_hosting_providers"
|
||||
version = "0.1.0"
|
||||
@@ -7342,6 +7307,7 @@ dependencies = [
|
||||
"agent_settings",
|
||||
"anyhow",
|
||||
"askpass",
|
||||
"async-channel 2.5.0",
|
||||
"buffer_diff",
|
||||
"call",
|
||||
"collections",
|
||||
@@ -7374,9 +7340,11 @@ dependencies = [
|
||||
"prompt_store",
|
||||
"proto",
|
||||
"rand 0.9.4",
|
||||
"release_channel",
|
||||
"remote",
|
||||
"remote_connection",
|
||||
"schemars 1.0.4",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"settings",
|
||||
@@ -22887,7 +22855,6 @@ dependencies = [
|
||||
"fs",
|
||||
"futures 0.3.32",
|
||||
"git",
|
||||
"git_graph",
|
||||
"git_hosting_providers",
|
||||
"git_ui",
|
||||
"go_to_line",
|
||||
|
||||
@@ -83,7 +83,6 @@ members = [
|
||||
"crates/fuzzy",
|
||||
"crates/fuzzy_nucleo",
|
||||
"crates/git",
|
||||
"crates/git_graph",
|
||||
"crates/git_hosting_providers",
|
||||
"crates/git_ui",
|
||||
"crates/go_to_line",
|
||||
@@ -339,7 +338,6 @@ fs = { path = "crates/fs" }
|
||||
fuzzy = { path = "crates/fuzzy" }
|
||||
fuzzy_nucleo = { path = "crates/fuzzy_nucleo" }
|
||||
git = { path = "crates/git" }
|
||||
git_graph = { path = "crates/git_graph" }
|
||||
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
||||
git_ui = { path = "crates/git_ui" }
|
||||
go_to_line = { path = "crates/go_to_line" }
|
||||
|
||||
@@ -97,7 +97,6 @@ extension.workspace = true
|
||||
file_finder.workspace = true
|
||||
fs = { workspace = true, features = ["test-support"] }
|
||||
git = { workspace = true, features = ["test-support"] }
|
||||
git_graph = { workspace = true, features = ["test-support"] }
|
||||
git_hosting_providers.workspace = true
|
||||
git_ui = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -11,7 +11,7 @@ use git::{
|
||||
repository::{CommitData, InitialGraphCommitData, RepoPath, Worktree as GitWorktree},
|
||||
status::{DiffStat, FileStatus, StatusCode, TrackedStatus},
|
||||
};
|
||||
use git_graph::GitGraph;
|
||||
use git_ui::git_graph::GitGraph;
|
||||
use git_ui::{git_panel::GitPanel, project_diff::ProjectDiff};
|
||||
use gpui::{
|
||||
AppContext as _, BackgroundExecutor, Entity, IntoElement as _, SharedString, TestAppContext,
|
||||
@@ -763,11 +763,9 @@ async fn test_remote_git_graph_data_and_search(
|
||||
.await;
|
||||
cx_a.update(|cx| {
|
||||
git_ui::init(cx);
|
||||
git_graph::init(cx);
|
||||
});
|
||||
cx_b.update(|cx| {
|
||||
git_ui::init(cx);
|
||||
git_graph::init(cx);
|
||||
});
|
||||
let active_call_a = cx_a.read(ActiveCall::global);
|
||||
|
||||
@@ -781,7 +779,7 @@ async fn test_remote_git_graph_data_and_search(
|
||||
|
||||
let search_query = "graph search match";
|
||||
let mut rng = StdRng::seed_from_u64(7);
|
||||
let commits = git_graph::generate_random_commit_dag(&mut rng, 12, true);
|
||||
let commits = git_ui::git_graph::generate_random_commit_dag(&mut rng, 12, true);
|
||||
|
||||
let dot_git = Path::new(path!("/project/.git"));
|
||||
client_a.fs().set_graph_commits(dot_git, commits.clone());
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
[package]
|
||||
name = "git_graph"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/git_graph.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
test-support = [
|
||||
"dep:rand",
|
||||
"project/test-support",
|
||||
"gpui/test-support",
|
||||
"remote_connection/test-support",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
async-channel.workspace = true
|
||||
collections.workspace = true
|
||||
db.workspace = true
|
||||
editor.workspace = true
|
||||
git.workspace = true
|
||||
git_ui.workspace = true
|
||||
gpui.workspace = true
|
||||
language.workspace = true
|
||||
menu.workspace = true
|
||||
picker.workspace = true
|
||||
project.workspace = true
|
||||
project_panel.workspace = true
|
||||
rand = { workspace = true, optional = true }
|
||||
release_channel.workspace = true
|
||||
search.workspace = true
|
||||
settings.workspace = true
|
||||
smallvec.workspace = true
|
||||
task.workspace = true
|
||||
theme.workspace = true
|
||||
theme_settings.workspace = true
|
||||
time.workspace = true
|
||||
ui.workspace = true
|
||||
workspace.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
db = { workspace = true, features = ["test-support"] }
|
||||
fs = { workspace = true, features = ["test-support"] }
|
||||
git = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
language_model.workspace = true
|
||||
project = { workspace = true, features = ["test-support"] }
|
||||
rand.workspace = true
|
||||
remote_connection = { workspace = true, features = ["test-support"] }
|
||||
serde_json.workspace = true
|
||||
settings = { workspace = true, features = ["test-support"] }
|
||||
workspace = { workspace = true, features = ["test-support"] }
|
||||
@@ -1 +0,0 @@
|
||||
../../LICENSE-GPL
|
||||
@@ -19,6 +19,7 @@ test-support = ["multi_buffer/test-support", "remote_connection/test-support"]
|
||||
agent_settings.workspace = true
|
||||
anyhow.workspace = true
|
||||
askpass.workspace = true
|
||||
async-channel.workspace = true
|
||||
buffer_diff.workspace = true
|
||||
call.workspace = true
|
||||
collections.workspace = true
|
||||
@@ -48,15 +49,18 @@ project.workspace = true
|
||||
prompt_store.workspace = true
|
||||
proto.workspace = true
|
||||
rand.workspace = true
|
||||
release_channel.workspace = true
|
||||
remote_connection.workspace = true
|
||||
remote.workspace = true
|
||||
schemars.workspace = true
|
||||
search.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
smallvec.workspace = true
|
||||
strum.workspace = true
|
||||
sysinfo.workspace = true
|
||||
task.workspace = true
|
||||
telemetry.workspace = true
|
||||
terminal.workspace = true
|
||||
theme.workspace = true
|
||||
@@ -78,7 +82,10 @@ windows.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
ctor.workspace = true
|
||||
db = { workspace = true, features = ["test-support"] }
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
fs = { workspace = true, features = ["test-support"] }
|
||||
git = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
indoc.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
|
||||
@@ -1306,7 +1306,7 @@ impl Render for CommitViewToolbar {
|
||||
.tooltip(Tooltip::text("Show in Git Graph"))
|
||||
.on_click(move |_, window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(crate::git_panel::OpenAtCommit {
|
||||
Box::new(crate::git_graph::OpenAtCommit {
|
||||
sha: sha_for_graph.clone(),
|
||||
}),
|
||||
cx,
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
use crate::{
|
||||
commit_tooltip::{CommitAvatar, CommitDetails, CommitTooltip},
|
||||
commit_view::CommitView,
|
||||
git_status_icon,
|
||||
};
|
||||
use collections::{BTreeMap, HashMap, IndexSet};
|
||||
use editor::Editor;
|
||||
use git::{
|
||||
@@ -10,11 +15,6 @@ use git::{
|
||||
},
|
||||
status::{FileStatus, StatusCode, TrackedStatus},
|
||||
};
|
||||
use git_ui::{
|
||||
commit_tooltip::{CommitAvatar, CommitDetails, CommitTooltip},
|
||||
commit_view::CommitView,
|
||||
git_status_icon,
|
||||
};
|
||||
use gpui::{
|
||||
Action, Anchor, AnyElement, App, Bounds, ClickEvent, ClipboardItem, DefiniteLength,
|
||||
DismissEvent, DragMoveEvent, ElementId, Empty, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
@@ -33,7 +33,6 @@ use project::{
|
||||
RepositoryEvent, RepositoryId,
|
||||
},
|
||||
};
|
||||
use project_panel::ProjectPanel;
|
||||
use search::{
|
||||
SearchOption, SearchOptions, SearchSource, SelectNextMatch, SelectPreviousMatch,
|
||||
ToggleCaseSensitive, buffer_search,
|
||||
@@ -340,24 +339,24 @@ struct SearchState {
|
||||
case_sensitive: bool,
|
||||
editor: Entity<Editor>,
|
||||
state: QueryState,
|
||||
pub matches: IndexSet<Oid>,
|
||||
pub selected_index: Option<usize>,
|
||||
matches: IndexSet<Oid>,
|
||||
selected_index: Option<usize>,
|
||||
}
|
||||
|
||||
pub struct SplitState {
|
||||
struct SplitState {
|
||||
left_ratio: f32,
|
||||
visible_left_ratio: f32,
|
||||
}
|
||||
|
||||
impl SplitState {
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
left_ratio: 1.0,
|
||||
visible_left_ratio: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right_ratio(&self) -> f32 {
|
||||
fn right_ratio(&self) -> f32 {
|
||||
1.0 - self.visible_left_ratio
|
||||
}
|
||||
|
||||
@@ -391,6 +390,8 @@ impl SplitState {
|
||||
actions!(
|
||||
git_graph,
|
||||
[
|
||||
/// Opens the Git Graph Tab.
|
||||
Open,
|
||||
/// Copies the SHA of the selected commit to the clipboard.
|
||||
CopyCommitSha,
|
||||
/// Copies a tag from the selected commit to the clipboard.
|
||||
@@ -410,6 +411,13 @@ actions!(
|
||||
]
|
||||
);
|
||||
|
||||
/// Opens the Git Graph Tab at a specific commit.
|
||||
#[derive(Clone, PartialEq, serde::Deserialize, schemars::JsonSchema, gpui::Action)]
|
||||
#[action(namespace = git_graph)]
|
||||
pub struct OpenAtCommit {
|
||||
pub sha: String,
|
||||
}
|
||||
|
||||
fn timestamp_format() -> &'static [BorrowedFormatItem<'static>] {
|
||||
static FORMAT: OnceLock<Vec<BorrowedFormatItem<'static>>> = OnceLock::new();
|
||||
FORMAT.get_or_init(|| {
|
||||
@@ -893,7 +901,7 @@ pub fn init(cx: &mut App) {
|
||||
|
||||
div.on_action({
|
||||
let workspace = workspace.clone();
|
||||
move |_: &git_ui::git_panel::Open, window, cx| {
|
||||
move |_: &Open, window, cx| {
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(repo) =
|
||||
@@ -918,33 +926,29 @@ pub fn init(cx: &mut App) {
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.on_action(
|
||||
move |action: &git_ui::git_panel::OpenAtCommit, window, cx| {
|
||||
let sha = action.sha.clone();
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(repo) =
|
||||
workspace.project().read(cx).active_repository(cx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let selected_repo_id = repo.read(cx).id;
|
||||
.on_action(move |action: &OpenAtCommit, window, cx| {
|
||||
let sha = action.sha.clone();
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(repo) = workspace.project().read(cx).active_repository(cx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let selected_repo_id = repo.read(cx).id;
|
||||
|
||||
let git_store =
|
||||
workspace.project().read(cx).git_store().clone();
|
||||
open_or_reuse_graph(
|
||||
workspace,
|
||||
selected_repo_id,
|
||||
git_store,
|
||||
LogSource::All,
|
||||
Some(sha),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
},
|
||||
)
|
||||
let git_store = workspace.project().read(cx).git_store().clone();
|
||||
open_or_reuse_graph(
|
||||
workspace,
|
||||
selected_repo_id,
|
||||
git_store,
|
||||
LogSource::All,
|
||||
Some(sha),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
},
|
||||
)
|
||||
});
|
||||
@@ -952,28 +956,32 @@ pub fn init(cx: &mut App) {
|
||||
.detach();
|
||||
}
|
||||
|
||||
/// Resolves a `git::FileHistory` target from a known project path (used by
|
||||
/// callers like `project_panel` that own a focused selection but cannot be
|
||||
/// referenced from this module due to dependency direction).
|
||||
pub fn resolve_file_history_target_from_project_path(
|
||||
workspace: &Workspace,
|
||||
project_path: &ProjectPath,
|
||||
cx: &App,
|
||||
) -> Option<(RepositoryId, LogSource)> {
|
||||
let git_store = workspace.project().read(cx).git_store();
|
||||
let (repo, repo_path) = git_store
|
||||
.read(cx)
|
||||
.repository_and_path_for_project_path(project_path, cx)?;
|
||||
let log_source = if repo_path.is_empty() {
|
||||
LogSource::All
|
||||
} else {
|
||||
LogSource::Path(repo_path)
|
||||
};
|
||||
Some((repo.read(cx).id, log_source))
|
||||
}
|
||||
|
||||
fn resolve_file_history_target(
|
||||
workspace: &Workspace,
|
||||
window: &Window,
|
||||
cx: &App,
|
||||
) -> Option<(RepositoryId, LogSource)> {
|
||||
if let Some(panel) = workspace.panel::<ProjectPanel>(cx)
|
||||
&& panel.read(cx).focus_handle(cx).contains_focused(window, cx)
|
||||
&& let Some(project_path) = panel.read(cx).selected_entry_project_path(cx)
|
||||
{
|
||||
let git_store = workspace.project().read(cx).git_store();
|
||||
let (repo, repo_path) = git_store
|
||||
.read(cx)
|
||||
.repository_and_path_for_project_path(&project_path, cx)?;
|
||||
let log_source = if repo_path.is_empty() {
|
||||
LogSource::All
|
||||
} else {
|
||||
LogSource::Path(repo_path)
|
||||
};
|
||||
return Some((repo.read(cx).id, log_source));
|
||||
}
|
||||
|
||||
if let Some(panel) = workspace.panel::<git_ui::git_panel::GitPanel>(cx)
|
||||
if let Some(panel) = workspace.panel::<crate::git_panel::GitPanel>(cx)
|
||||
&& panel.read(cx).focus_handle(cx).contains_focused(window, cx)
|
||||
&& let Some((repository, repo_path)) = panel.read(cx).selected_file_history_target()
|
||||
{
|
||||
@@ -997,7 +1005,7 @@ fn resolve_file_history_target(
|
||||
Some((repo.read(cx).id, LogSource::Path(repo_path)))
|
||||
}
|
||||
|
||||
fn open_or_reuse_graph(
|
||||
pub fn open_or_reuse_graph(
|
||||
workspace: &mut Workspace,
|
||||
repo_id: RepositoryId,
|
||||
git_store: Entity<GitStore>,
|
||||
@@ -2314,22 +2322,6 @@ impl GitGraph {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn get_remote(
|
||||
&self,
|
||||
repository: &Repository,
|
||||
_window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<GitRemote> {
|
||||
let remote_url = repository.default_remote_url()?;
|
||||
let provider_registry = GitHostingProviderRegistry::default_global(cx);
|
||||
let (provider, parsed) = parse_git_remote_url(provider_registry, &remote_url)?;
|
||||
Some(GitRemote {
|
||||
host: provider,
|
||||
owner: parsed.owner.into(),
|
||||
repo: parsed.repo.into(),
|
||||
})
|
||||
}
|
||||
|
||||
fn render_search_bar(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let color = cx.theme().colors();
|
||||
let query_focus_handle = self
|
||||
@@ -2536,7 +2528,16 @@ impl GitGraph {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let remote = repository.update(cx, |repo, cx| self.get_remote(repo, window, cx));
|
||||
let remote = repository.update(cx, |repo, cx| {
|
||||
let remote_url = repo.default_remote_url()?;
|
||||
let provider_registry = GitHostingProviderRegistry::default_global(cx);
|
||||
let (provider, parsed) = parse_git_remote_url(provider_registry, &remote_url)?;
|
||||
Some(GitRemote {
|
||||
host: provider,
|
||||
owner: parsed.owner.into(),
|
||||
repo: parsed.repo.into(),
|
||||
})
|
||||
});
|
||||
|
||||
let avatar = {
|
||||
let author_email_for_avatar = if author_email.is_empty() {
|
||||
@@ -2733,7 +2734,7 @@ impl GitGraph {
|
||||
})
|
||||
.when_some(remote.clone(), |this, remote| {
|
||||
let provider_name = remote.host.name();
|
||||
let icon = git_ui::get_provider_icon(provider_name.as_str());
|
||||
let icon = crate::get_provider_icon(provider_name.as_str());
|
||||
let parsed_remote = ParsedGitRemote {
|
||||
owner: remote.owner.as_ref().into(),
|
||||
repo: remote.repo.as_ref().into(),
|
||||
@@ -4084,6 +4085,11 @@ impl GitGraph {
|
||||
.map(|commit| commit.data.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn log_source_for_test(&self) -> &LogSource {
|
||||
&self.log_source
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a random commit DAG suitable for testing git graph rendering.
|
||||
@@ -4219,9 +4225,7 @@ mod tests {
|
||||
cx.set_global(settings_store);
|
||||
theme_settings::init(theme::LoadThemes::JustBase, cx);
|
||||
language_model::init(cx);
|
||||
git_ui::init(cx);
|
||||
project_panel::init(cx);
|
||||
init(cx);
|
||||
crate::init(cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4794,24 +4798,14 @@ mod tests {
|
||||
});
|
||||
|
||||
repository.update(cx, |repo, cx| {
|
||||
repo.graph_data(
|
||||
crate::LogSource::default(),
|
||||
crate::LogOrder::default(),
|
||||
0..usize::MAX,
|
||||
cx,
|
||||
);
|
||||
repo.graph_data(LogSource::default(), LogOrder::default(), 0..usize::MAX, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
let graph_commits: Vec<Arc<InitialGraphCommitData>> = repository.update(cx, |repo, cx| {
|
||||
repo.graph_data(
|
||||
crate::LogSource::default(),
|
||||
crate::LogOrder::default(),
|
||||
0..usize::MAX,
|
||||
cx,
|
||||
)
|
||||
.commits
|
||||
.to_vec()
|
||||
repo.graph_data(LogSource::default(), LogOrder::default(), 0..usize::MAX, cx)
|
||||
.commits
|
||||
.to_vec()
|
||||
});
|
||||
|
||||
let mut graph_data = GraphData::new(8);
|
||||
@@ -4865,12 +4859,7 @@ mod tests {
|
||||
});
|
||||
|
||||
repository.update(cx, |repo, cx| {
|
||||
repo.graph_data(
|
||||
crate::LogSource::default(),
|
||||
crate::LogOrder::default(),
|
||||
0..usize::MAX,
|
||||
cx,
|
||||
);
|
||||
repo.graph_data(LogSource::default(), LogOrder::default(), 0..usize::MAX, cx);
|
||||
});
|
||||
|
||||
project
|
||||
@@ -4888,7 +4877,7 @@ mod tests {
|
||||
"initial repository scan should emit HeadChanged"
|
||||
);
|
||||
let commit_count_after = repository.read_with(cx, |repo, _| {
|
||||
repo.get_graph_data(crate::LogSource::default(), crate::LogOrder::default())
|
||||
repo.get_graph_data(LogSource::default(), LogOrder::default())
|
||||
.map(|data| data.commit_data.len())
|
||||
.unwrap()
|
||||
});
|
||||
@@ -4927,18 +4916,13 @@ mod tests {
|
||||
});
|
||||
|
||||
repository.update(cx, |repo, cx| {
|
||||
repo.graph_data(
|
||||
crate::LogSource::default(),
|
||||
crate::LogOrder::default(),
|
||||
0..usize::MAX,
|
||||
cx,
|
||||
);
|
||||
repo.graph_data(LogSource::default(), LogOrder::default(), 0..usize::MAX, cx);
|
||||
});
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
let error = repository.read_with(cx, |repo, _| {
|
||||
repo.get_graph_data(crate::LogSource::default(), crate::LogOrder::default())
|
||||
repo.get_graph_data(LogSource::default(), LogOrder::default())
|
||||
.and_then(|data| data.error.clone())
|
||||
});
|
||||
|
||||
@@ -5070,14 +5054,12 @@ mod tests {
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_file_history_action_uses_focused_source_and_reuses_matching_graph(
|
||||
cx: &mut TestAppContext,
|
||||
) {
|
||||
async fn test_file_history_action_uses_git_panel_and_editor_sources(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
Path::new("/project"),
|
||||
Path::new(util::path!("/project")),
|
||||
json!({
|
||||
".git": {},
|
||||
"tracked1.txt": "tracked 1",
|
||||
@@ -5085,15 +5067,22 @@ mod tests {
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
fs.set_status_for_repo(
|
||||
Path::new(util::path!("/project/.git")),
|
||||
&[
|
||||
("tracked1.txt", StatusCode::Modified.worktree()),
|
||||
("tracked2.txt", StatusCode::Modified.worktree()),
|
||||
],
|
||||
);
|
||||
|
||||
let commits = vec![Arc::new(InitialGraphCommitData {
|
||||
sha: Oid::from_bytes(&[1; 20]).unwrap(),
|
||||
parents: smallvec![],
|
||||
ref_names: vec!["HEAD".into(), "refs/heads/main".into()],
|
||||
})];
|
||||
fs.set_graph_commits(Path::new("/project/.git"), commits);
|
||||
fs.set_graph_commits(Path::new(util::path!("/project/.git")), commits);
|
||||
|
||||
let project = Project::test(fs.clone(), [Path::new("/project")], cx).await;
|
||||
let project = Project::test(fs.clone(), [Path::new(util::path!("/project"))], cx).await;
|
||||
cx.run_until_parked();
|
||||
|
||||
let repository = project.read_with(cx, |project, cx| {
|
||||
@@ -5127,18 +5116,10 @@ mod tests {
|
||||
})
|
||||
.expect("window should be available");
|
||||
cx.background_executor.allow_parking();
|
||||
let project_panel = cx
|
||||
.foreground_executor()
|
||||
.clone()
|
||||
.block_test(ProjectPanel::load(
|
||||
weak_workspace.clone(),
|
||||
async_window_cx.clone(),
|
||||
))
|
||||
.expect("project panel should load");
|
||||
let git_panel = cx
|
||||
.foreground_executor()
|
||||
.clone()
|
||||
.block_test(git_ui::git_panel::GitPanel::load(
|
||||
.block_test(crate::git_panel::GitPanel::load(
|
||||
weak_workspace,
|
||||
async_window_cx,
|
||||
))
|
||||
@@ -5149,21 +5130,20 @@ mod tests {
|
||||
.update(cx, |multi, window, cx| {
|
||||
let workspace = multi.workspace();
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.add_panel(project_panel.clone(), window, cx);
|
||||
workspace.add_panel(git_panel.clone(), window, cx);
|
||||
});
|
||||
})
|
||||
.expect("workspace window should be available");
|
||||
cx.executor().advance_clock(Duration::from_millis(100));
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace_window
|
||||
.update(cx, |multi, window, cx| {
|
||||
let workspace = multi.workspace();
|
||||
project_panel.update(cx, |panel, cx| {
|
||||
panel.select_path_for_test(tracked1.clone(), cx)
|
||||
.update(cx, |_, window, cx| {
|
||||
git_panel.update(cx, |panel, cx| {
|
||||
panel.select_entry_by_path(tracked1.clone(), window, cx);
|
||||
});
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.focus_panel::<ProjectPanel>(window, cx);
|
||||
git_panel.update(cx, |panel, cx| {
|
||||
panel.focus_handle(cx).focus(window, cx);
|
||||
});
|
||||
})
|
||||
.expect("workspace window should be available");
|
||||
@@ -5185,13 +5165,12 @@ mod tests {
|
||||
});
|
||||
|
||||
workspace_window
|
||||
.update(cx, |multi, window, cx| {
|
||||
let workspace = multi.workspace();
|
||||
.update(cx, |_, window, cx| {
|
||||
git_panel.update(cx, |panel, cx| {
|
||||
panel.select_entry_by_path(tracked1.clone(), window, cx);
|
||||
});
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.focus_panel::<git_ui::git_panel::GitPanel>(window, cx);
|
||||
git_panel.update(cx, |panel, cx| {
|
||||
panel.focus_handle(cx).focus(window, cx);
|
||||
});
|
||||
})
|
||||
.expect("workspace window should be available");
|
||||
@@ -134,21 +134,6 @@ actions!(
|
||||
]
|
||||
);
|
||||
|
||||
actions!(
|
||||
git_graph,
|
||||
[
|
||||
/// Opens the Git Graph Tab.
|
||||
Open,
|
||||
]
|
||||
);
|
||||
|
||||
/// Opens the Git Graph Tab at a specific commit.
|
||||
#[derive(Clone, PartialEq, serde::Deserialize, schemars::JsonSchema, gpui::Action)]
|
||||
#[action(namespace = git_graph)]
|
||||
pub struct OpenAtCommit {
|
||||
pub sha: String,
|
||||
}
|
||||
|
||||
fn prompt<T>(
|
||||
msg: &str,
|
||||
detail: Option<&str>,
|
||||
@@ -5027,10 +5012,14 @@ impl GitPanel {
|
||||
IconButton::new("git-graph-button", IconName::GitGraph)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(|_window, cx| {
|
||||
Tooltip::for_action("Open Git Graph", &Open, cx)
|
||||
Tooltip::for_action(
|
||||
"Open Git Graph",
|
||||
&crate::git_graph::Open,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(Open.boxed_clone(), cx)
|
||||
window.dispatch_action(crate::git_graph::Open.boxed_clone(), cx)
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -36,6 +36,7 @@ pub mod commit_tooltip;
|
||||
pub mod commit_view;
|
||||
mod conflict_view;
|
||||
pub mod file_diff_view;
|
||||
pub mod git_graph;
|
||||
pub mod git_panel;
|
||||
mod git_panel_settings;
|
||||
pub mod git_picker;
|
||||
@@ -69,6 +70,7 @@ pub fn get_provider_icon(name: &str) -> IconName {
|
||||
pub fn init(cx: &mut App) {
|
||||
editor::set_blame_renderer(blame_ui::GitBlameRenderer, cx);
|
||||
commit_view::init(cx);
|
||||
git_graph::init(cx);
|
||||
|
||||
cx.observe_new(|editor: &mut Editor, _, cx| {
|
||||
conflict_view::register_editor(editor, editor.buffer().clone(), cx);
|
||||
|
||||
@@ -55,6 +55,7 @@ fs.workspace = true
|
||||
client = { workspace = true, features = ["test-support"] }
|
||||
criterion.workspace = true
|
||||
editor = { workspace = true, features = ["test-support"] }
|
||||
git_ui = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
language = { workspace = true, features = ["test-support"] }
|
||||
remote_connection = { workspace = true, features = ["test-support"] }
|
||||
|
||||
@@ -527,6 +527,50 @@ pub fn init(cx: &mut App) {
|
||||
panel.update(cx, |panel, cx| panel.delete(action, window, cx));
|
||||
}
|
||||
});
|
||||
|
||||
// Forwards `git::FileHistory` to `git_ui::git_graph` when the project
|
||||
// panel is the focused source of selection. Lives here (and not in
|
||||
// `git_ui`) so that `git_ui` does not need to depend on
|
||||
// `project_panel`, which would create a dependency cycle.
|
||||
workspace.register_action_renderer(|div, workspace, window, cx| {
|
||||
let Some(panel) = workspace.panel::<ProjectPanel>(cx) else {
|
||||
return div;
|
||||
};
|
||||
if !panel.read(cx).focus_handle(cx).contains_focused(window, cx) {
|
||||
return div;
|
||||
}
|
||||
if panel.read(cx).selected_entry_project_path(cx).is_none() {
|
||||
return div;
|
||||
}
|
||||
let workspace = workspace.weak_handle();
|
||||
div.capture_action(move |_: &git::FileHistory, window, cx| {
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(panel) = workspace.panel::<ProjectPanel>(cx) else {
|
||||
return;
|
||||
};
|
||||
let Some(project_path) = panel.read(cx).selected_entry_project_path(cx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some((repo_id, log_source)) =
|
||||
git_ui::git_graph::resolve_file_history_target_from_project_path(
|
||||
workspace,
|
||||
&project_path,
|
||||
cx,
|
||||
)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let git_store = workspace.project().read(cx).git_store().clone();
|
||||
git_ui::git_graph::open_or_reuse_graph(
|
||||
workspace, repo_id, git_store, log_source, None, window, cx,
|
||||
);
|
||||
})
|
||||
.log_err();
|
||||
cx.stop_propagation();
|
||||
})
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
use super::*;
|
||||
// use crate::undo::tests::{build_create_operation, build_rename_operation};
|
||||
use collections::HashSet;
|
||||
use editor::MultiBufferOffset;
|
||||
use editor::{Editor, MultiBufferOffset};
|
||||
use git::{
|
||||
Oid,
|
||||
repository::{InitialGraphCommitData, LogSource, RepoPath},
|
||||
};
|
||||
use gpui::{Empty, Entity, TestAppContext, VisualTestContext};
|
||||
use menu::Cancel;
|
||||
use pretty_assertions::assert_eq;
|
||||
use project::{FakeFs, ProjectPath};
|
||||
use serde_json::json;
|
||||
use settings::{ProjectPanelAutoOpenSettings, SettingsStore};
|
||||
use smallvec::smallvec;
|
||||
use std::path::{Path, PathBuf};
|
||||
use util::{path, paths::PathStyle, rel_path::rel_path};
|
||||
use workspace::{
|
||||
@@ -167,6 +172,254 @@ async fn test_opening_file(cx: &mut gpui::TestAppContext) {
|
||||
ensure_single_file_is_opened(&workspace, "test/second.rs", cx);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_file_history_action_uses_focused_project_panel_selection(
|
||||
cx: &mut gpui::TestAppContext,
|
||||
) {
|
||||
init_test_with_git_ui(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
Path::new("/project"),
|
||||
json!({
|
||||
".git": {},
|
||||
"tracked1.txt": "tracked 1",
|
||||
"tracked2.txt": "tracked 2",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let commits = vec![Arc::new(InitialGraphCommitData {
|
||||
sha: Oid::from_bytes(&[1; 20]).unwrap(),
|
||||
parents: smallvec![],
|
||||
ref_names: vec!["HEAD".into(), "refs/heads/main".into()],
|
||||
})];
|
||||
fs.set_graph_commits(Path::new("/project/.git"), commits);
|
||||
|
||||
let project = Project::test(fs.clone(), [Path::new("/project")], cx).await;
|
||||
cx.run_until_parked();
|
||||
|
||||
let repository = project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.active_repository(cx)
|
||||
.expect("should have active repository")
|
||||
});
|
||||
let project_panel_repo_path = RepoPath::new(&"tracked1.txt").unwrap();
|
||||
let editor_repo_path = RepoPath::new(&"tracked2.txt").unwrap();
|
||||
let project_panel_path = repository
|
||||
.read_with(cx, |repository, cx| {
|
||||
repository.repo_path_to_project_path(&project_panel_repo_path, cx)
|
||||
})
|
||||
.expect("project panel path should resolve");
|
||||
let editor_path = repository
|
||||
.read_with(cx, |repository, cx| {
|
||||
repository.repo_path_to_project_path(&editor_repo_path, cx)
|
||||
})
|
||||
.expect("editor path should resolve");
|
||||
|
||||
let (multi_workspace, cx) =
|
||||
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
|
||||
let workspace = multi_workspace.read_with(&*cx, |multi_workspace, _| {
|
||||
multi_workspace.workspace().clone()
|
||||
});
|
||||
let project_panel = multi_workspace.update_in(cx, |multi_workspace, window, cx| {
|
||||
let workspace = multi_workspace.workspace();
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
let project_panel = ProjectPanel::new(workspace, window, cx);
|
||||
workspace.add_panel(project_panel.clone(), window, cx);
|
||||
project_panel
|
||||
})
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
let editor_buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer(editor_path.clone(), cx)
|
||||
})
|
||||
.await
|
||||
.expect("editor buffer should open");
|
||||
multi_workspace.update_in(cx, |multi_workspace, window, cx| {
|
||||
let workspace = multi_workspace.workspace();
|
||||
let multibuffer = cx.new(|cx| {
|
||||
let mut multibuffer = editor::MultiBuffer::new(language::Capability::ReadWrite);
|
||||
multibuffer.set_excerpts_for_buffer(
|
||||
editor_buffer.clone(),
|
||||
[Default::default()..editor_buffer.read(cx).max_point()],
|
||||
0,
|
||||
cx,
|
||||
);
|
||||
multibuffer
|
||||
});
|
||||
let editor =
|
||||
cx.new(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), window, cx));
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
|
||||
});
|
||||
editor.update(cx, |editor, cx| {
|
||||
window.focus(&editor.focus_handle(cx), cx);
|
||||
});
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
multi_workspace.update_in(cx, |_multi_workspace, window, cx| {
|
||||
project_panel.update(cx, |panel, cx| {
|
||||
panel.select_path_for_test(project_panel_path.clone(), cx);
|
||||
});
|
||||
project_panel.update(cx, |panel, cx| {
|
||||
panel.focus_handle(cx).focus(window, cx);
|
||||
});
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update(|window, cx| {
|
||||
window.dispatch_action(Box::new(git::FileHistory), cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace.read_with(&*cx, |workspace, cx| {
|
||||
let graphs = workspace
|
||||
.items_of_type::<git_ui::git_graph::GitGraph>(cx)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(graphs.len(), 1);
|
||||
assert_eq!(
|
||||
graphs[0].read(cx).log_source_for_test(),
|
||||
&LogSource::Path(project_panel_repo_path)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_file_history_action_does_not_fall_back_to_editor_when_focused_project_panel_selection_has_no_git_repo(
|
||||
cx: &mut gpui::TestAppContext,
|
||||
) {
|
||||
init_test_with_git_ui(cx);
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_tree(
|
||||
Path::new("/git-project"),
|
||||
json!({
|
||||
".git": {},
|
||||
"tracked.txt": "tracked",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
fs.insert_tree(
|
||||
Path::new("/plain-project"),
|
||||
json!({
|
||||
"plain.txt": "plain",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
fs.set_graph_commits(
|
||||
Path::new("/git-project/.git"),
|
||||
vec![Arc::new(InitialGraphCommitData {
|
||||
sha: Oid::from_bytes(&[1; 20]).unwrap(),
|
||||
parents: smallvec![],
|
||||
ref_names: vec!["HEAD".into(), "refs/heads/main".into()],
|
||||
})],
|
||||
);
|
||||
|
||||
let project = Project::test(
|
||||
fs.clone(),
|
||||
[Path::new("/git-project"), Path::new("/plain-project")],
|
||||
cx,
|
||||
)
|
||||
.await;
|
||||
cx.run_until_parked();
|
||||
|
||||
let repository = project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.active_repository(cx)
|
||||
.expect("should have active repository")
|
||||
});
|
||||
let editor_repo_path = RepoPath::new(&"tracked.txt").unwrap();
|
||||
let editor_path = repository
|
||||
.read_with(cx, |repository, cx| {
|
||||
repository.repo_path_to_project_path(&editor_repo_path, cx)
|
||||
})
|
||||
.expect("editor path should resolve");
|
||||
let plain_worktree_id = project.read_with(cx, |project, cx| {
|
||||
project
|
||||
.worktree_for_root_name("plain-project", cx)
|
||||
.expect("plain worktree should exist")
|
||||
.read(cx)
|
||||
.id()
|
||||
});
|
||||
let plain_project_path = ProjectPath {
|
||||
worktree_id: plain_worktree_id,
|
||||
path: rel_path("plain.txt").into(),
|
||||
};
|
||||
|
||||
let (multi_workspace, cx) =
|
||||
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
|
||||
let workspace = multi_workspace.read_with(&*cx, |multi_workspace, _| {
|
||||
multi_workspace.workspace().clone()
|
||||
});
|
||||
let project_panel = multi_workspace.update_in(cx, |multi_workspace, window, cx| {
|
||||
let workspace = multi_workspace.workspace();
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
let project_panel = ProjectPanel::new(workspace, window, cx);
|
||||
workspace.add_panel(project_panel.clone(), window, cx);
|
||||
project_panel
|
||||
})
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
let editor_buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer(editor_path.clone(), cx)
|
||||
})
|
||||
.await
|
||||
.expect("editor buffer should open");
|
||||
multi_workspace.update_in(cx, |multi_workspace, window, cx| {
|
||||
let workspace = multi_workspace.workspace();
|
||||
let multibuffer = cx.new(|cx| {
|
||||
let mut multibuffer = editor::MultiBuffer::new(language::Capability::ReadWrite);
|
||||
multibuffer.set_excerpts_for_buffer(
|
||||
editor_buffer.clone(),
|
||||
[Default::default()..editor_buffer.read(cx).max_point()],
|
||||
0,
|
||||
cx,
|
||||
);
|
||||
multibuffer
|
||||
});
|
||||
let editor =
|
||||
cx.new(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), window, cx));
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
|
||||
});
|
||||
editor.update(cx, |editor, cx| {
|
||||
window.focus(&editor.focus_handle(cx), cx);
|
||||
});
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
multi_workspace.update_in(cx, |_multi_workspace, window, cx| {
|
||||
project_panel.update(cx, |panel, cx| {
|
||||
panel.select_path_for_test(plain_project_path.clone(), cx);
|
||||
});
|
||||
project_panel.update(cx, |panel, cx| {
|
||||
panel.focus_handle(cx).focus(window, cx);
|
||||
});
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
cx.update(|window, cx| {
|
||||
window.dispatch_action(Box::new(git::FileHistory), cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
|
||||
workspace.read_with(&*cx, |workspace, cx| {
|
||||
assert_eq!(
|
||||
workspace
|
||||
.items_of_type::<git_ui::git_graph::GitGraph>(cx)
|
||||
.count(),
|
||||
0
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_exclusions_in_visible_list(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
@@ -10412,6 +10665,27 @@ fn init_test_with_editor(cx: &mut TestAppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
fn init_test_with_git_ui(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
let app_state = AppState::test(cx);
|
||||
theme_settings::init(theme::LoadThemes::JustBase, cx);
|
||||
editor::init(cx);
|
||||
git_ui::init(cx);
|
||||
crate::init(cx);
|
||||
workspace::init(app_state, cx);
|
||||
|
||||
cx.update_global::<SettingsStore, _>(|store, cx| {
|
||||
store.update_user_settings(cx, |settings| {
|
||||
settings
|
||||
.project_panel
|
||||
.get_or_insert_default()
|
||||
.auto_fold_dirs = Some(false);
|
||||
settings.project.worktree.file_scan_exclusions = Some(Vec::new())
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn set_auto_open_settings(
|
||||
cx: &mut TestAppContext,
|
||||
auto_open_settings: ProjectPanelAutoOpenSettings,
|
||||
|
||||
@@ -113,7 +113,6 @@ file_finder.workspace = true
|
||||
fs.workspace = true
|
||||
futures.workspace = true
|
||||
git.workspace = true
|
||||
git_graph.workspace = true
|
||||
git_hosting_providers.workspace = true
|
||||
git_ui.workspace = true
|
||||
go_to_line.workspace = true
|
||||
|
||||
@@ -767,7 +767,6 @@ fn main() {
|
||||
notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||
collab_ui::init(&app_state, cx);
|
||||
git_ui::init(cx);
|
||||
git_graph::init(cx);
|
||||
feedback::init(cx);
|
||||
markdown_preview::init(cx);
|
||||
csv_preview::init(cx);
|
||||
|
||||
@@ -5478,7 +5478,6 @@ mod tests {
|
||||
);
|
||||
language_models::init(app_state.user_store.clone(), app_state.client.clone(), cx);
|
||||
web_search::init(cx);
|
||||
git_graph::init(cx);
|
||||
web_search_providers::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||
let prompt_builder = PromptBuilder::load(app_state.fs.clone(), false, cx);
|
||||
project::AgentRegistryStore::init_global(
|
||||
|
||||
Reference in new issue
Block a user