remote ssh: Make "get permalink to line" work (#19366)
This makes the `editor: copy permalink to line` and `editor: copy permalink to line` actions work in SSH remote projects. Previously it would only work in local projects. Demo: https://github.com/user-attachments/assets/a8012152-b631-4b34-9ff2-e4d033c97dee Release Notes: - N/A
This commit is contained in:
parent
c186e99a3d
commit
4be9da2641
9 changed files with 219 additions and 79 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -8472,6 +8472,7 @@ dependencies = [
|
||||||
"terminal",
|
"terminal",
|
||||||
"text",
|
"text",
|
||||||
"unindent",
|
"unindent",
|
||||||
|
"url",
|
||||||
"util",
|
"util",
|
||||||
"which 6.0.3",
|
"which 6.0.3",
|
||||||
"windows 0.58.0",
|
"windows 0.58.0",
|
||||||
|
@ -9147,6 +9148,8 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.30",
|
"futures 0.3.30",
|
||||||
|
"git",
|
||||||
|
"git_hosting_providers",
|
||||||
"gpui",
|
"gpui",
|
||||||
"http_client",
|
"http_client",
|
||||||
"language",
|
"language",
|
||||||
|
|
|
@ -48,7 +48,6 @@ mod signature_help;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
use ::git::diff::DiffHunkStatus;
|
use ::git::diff::DiffHunkStatus;
|
||||||
use ::git::{parse_git_remote_url, BuildPermalinkParams, GitHostingProviderRegistry};
|
|
||||||
pub(crate) use actions::*;
|
pub(crate) use actions::*;
|
||||||
use aho_corasick::AhoCorasick;
|
use aho_corasick::AhoCorasick;
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
|
@ -11488,11 +11487,8 @@ impl Editor {
|
||||||
snapshot.line_len(buffer_row) == 0
|
snapshot.line_len(buffer_row) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
|
fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Task<Result<url::Url>> {
|
||||||
let (path, selection, repo) = maybe!({
|
let buffer_and_selection = maybe!({
|
||||||
let project_handle = self.project.as_ref()?.clone();
|
|
||||||
let project = project_handle.read(cx);
|
|
||||||
|
|
||||||
let selection = self.selections.newest::<Point>(cx);
|
let selection = self.selections.newest::<Point>(cx);
|
||||||
let selection_range = selection.range();
|
let selection_range = selection.range();
|
||||||
|
|
||||||
|
@ -11516,64 +11512,58 @@ impl Editor {
|
||||||
(buffer.clone(), selection)
|
(buffer.clone(), selection)
|
||||||
};
|
};
|
||||||
|
|
||||||
let path = buffer
|
Some((buffer, selection))
|
||||||
.read(cx)
|
});
|
||||||
.file()?
|
|
||||||
.as_local()?
|
let Some((buffer, selection)) = buffer_and_selection else {
|
||||||
.path()
|
return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
|
||||||
.to_str()?
|
};
|
||||||
.to_string();
|
|
||||||
let repo = project.get_repo(&buffer.read(cx).project_path(cx)?, cx)?;
|
let Some(project) = self.project.as_ref() else {
|
||||||
Some((path, selection, repo))
|
return Task::ready(Err(anyhow!("editor does not have project")));
|
||||||
|
};
|
||||||
|
|
||||||
|
project.update(cx, |project, cx| {
|
||||||
|
project.get_permalink_to_line(&buffer, selection, cx)
|
||||||
})
|
})
|
||||||
.ok_or_else(|| anyhow!("unable to open git repository"))?;
|
|
||||||
|
|
||||||
const REMOTE_NAME: &str = "origin";
|
|
||||||
let origin_url = repo
|
|
||||||
.remote_url(REMOTE_NAME)
|
|
||||||
.ok_or_else(|| anyhow!("remote \"{REMOTE_NAME}\" not found"))?;
|
|
||||||
let sha = repo
|
|
||||||
.head_sha()
|
|
||||||
.ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
|
|
||||||
|
|
||||||
let (provider, remote) =
|
|
||||||
parse_git_remote_url(GitHostingProviderRegistry::default_global(cx), &origin_url)
|
|
||||||
.ok_or_else(|| anyhow!("failed to parse Git remote URL"))?;
|
|
||||||
|
|
||||||
Ok(provider.build_permalink(
|
|
||||||
remote,
|
|
||||||
BuildPermalinkParams {
|
|
||||||
sha: &sha,
|
|
||||||
path: &path,
|
|
||||||
selection: Some(selection),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
|
pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
|
||||||
let permalink = self.get_permalink_to_line(cx);
|
let permalink_task = self.get_permalink_to_line(cx);
|
||||||
|
let workspace = self.workspace();
|
||||||
|
|
||||||
match permalink {
|
cx.spawn(|_, mut cx| async move {
|
||||||
Ok(permalink) => {
|
match permalink_task.await {
|
||||||
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
|
Ok(permalink) => {
|
||||||
}
|
cx.update(|cx| {
|
||||||
Err(err) => {
|
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
|
||||||
let message = format!("Failed to copy permalink: {err}");
|
|
||||||
|
|
||||||
Err::<(), anyhow::Error>(err).log_err();
|
|
||||||
|
|
||||||
if let Some(workspace) = self.workspace() {
|
|
||||||
workspace.update(cx, |workspace, cx| {
|
|
||||||
struct CopyPermalinkToLine;
|
|
||||||
|
|
||||||
workspace.show_toast(
|
|
||||||
Toast::new(NotificationId::unique::<CopyPermalinkToLine>(), message),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let message = format!("Failed to copy permalink: {err}");
|
||||||
|
|
||||||
|
Err::<(), anyhow::Error>(err).log_err();
|
||||||
|
|
||||||
|
if let Some(workspace) = workspace {
|
||||||
|
workspace
|
||||||
|
.update(&mut cx, |workspace, cx| {
|
||||||
|
struct CopyPermalinkToLine;
|
||||||
|
|
||||||
|
workspace.show_toast(
|
||||||
|
Toast::new(
|
||||||
|
NotificationId::unique::<CopyPermalinkToLine>(),
|
||||||
|
message,
|
||||||
|
),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_file_location(&mut self, _: &CopyFileLocation, cx: &mut ViewContext<Self>) {
|
pub fn copy_file_location(&mut self, _: &CopyFileLocation, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -11586,29 +11576,41 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
|
pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
|
||||||
let permalink = self.get_permalink_to_line(cx);
|
let permalink_task = self.get_permalink_to_line(cx);
|
||||||
|
let workspace = self.workspace();
|
||||||
|
|
||||||
match permalink {
|
cx.spawn(|_, mut cx| async move {
|
||||||
Ok(permalink) => {
|
match permalink_task.await {
|
||||||
cx.open_url(permalink.as_ref());
|
Ok(permalink) => {
|
||||||
}
|
cx.update(|cx| {
|
||||||
Err(err) => {
|
cx.open_url(permalink.as_ref());
|
||||||
let message = format!("Failed to open permalink: {err}");
|
|
||||||
|
|
||||||
Err::<(), anyhow::Error>(err).log_err();
|
|
||||||
|
|
||||||
if let Some(workspace) = self.workspace() {
|
|
||||||
workspace.update(cx, |workspace, cx| {
|
|
||||||
struct OpenPermalinkToLine;
|
|
||||||
|
|
||||||
workspace.show_toast(
|
|
||||||
Toast::new(NotificationId::unique::<OpenPermalinkToLine>(), message),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let message = format!("Failed to open permalink: {err}");
|
||||||
|
|
||||||
|
Err::<(), anyhow::Error>(err).log_err();
|
||||||
|
|
||||||
|
if let Some(workspace) = workspace {
|
||||||
|
workspace
|
||||||
|
.update(&mut cx, |workspace, cx| {
|
||||||
|
struct OpenPermalinkToLine;
|
||||||
|
|
||||||
|
workspace.show_toast(
|
||||||
|
Toast::new(
|
||||||
|
NotificationId::unique::<OpenPermalinkToLine>(),
|
||||||
|
message,
|
||||||
|
),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a row highlight for the given range. If a row has multiple highlights, the
|
/// Adds a row highlight for the given range. If a row has multiple highlights, the
|
||||||
|
|
|
@ -69,6 +69,7 @@ snippet_provider.workspace = true
|
||||||
terminal.workspace = true
|
terminal.workspace = true
|
||||||
text.workspace = true
|
text.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
|
url.workspace = true
|
||||||
which.workspace = true
|
which.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
||||||
worktree_store::{WorktreeStore, WorktreeStoreEvent},
|
worktree_store::{WorktreeStore, WorktreeStoreEvent},
|
||||||
Item, NoRepositoryError, ProjectPath,
|
Item, NoRepositoryError, ProjectPath,
|
||||||
};
|
};
|
||||||
|
use ::git::{parse_git_remote_url, BuildPermalinkParams, GitHostingProviderRegistry};
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use collections::{hash_map, HashMap, HashSet};
|
use collections::{hash_map, HashMap, HashSet};
|
||||||
|
@ -23,7 +24,7 @@ use language::{
|
||||||
};
|
};
|
||||||
use rpc::{proto, AnyProtoClient, ErrorExt as _, TypedEnvelope};
|
use rpc::{proto, AnyProtoClient, ErrorExt as _, TypedEnvelope};
|
||||||
use smol::channel::Receiver;
|
use smol::channel::Receiver;
|
||||||
use std::{io, path::Path, str::FromStr as _, sync::Arc, time::Instant};
|
use std::{io, ops::Range, path::Path, str::FromStr as _, sync::Arc, time::Instant};
|
||||||
use text::BufferId;
|
use text::BufferId;
|
||||||
use util::{debug_panic, maybe, ResultExt as _, TryFutureExt};
|
use util::{debug_panic, maybe, ResultExt as _, TryFutureExt};
|
||||||
use worktree::{File, PathChange, ProjectEntryId, UpdatedGitRepositoriesSet, Worktree, WorktreeId};
|
use worktree::{File, PathChange, ProjectEntryId, UpdatedGitRepositoriesSet, Worktree, WorktreeId};
|
||||||
|
@ -971,6 +972,7 @@ impl BufferStore {
|
||||||
client.add_model_request_handler(Self::handle_save_buffer);
|
client.add_model_request_handler(Self::handle_save_buffer);
|
||||||
client.add_model_request_handler(Self::handle_blame_buffer);
|
client.add_model_request_handler(Self::handle_blame_buffer);
|
||||||
client.add_model_request_handler(Self::handle_reload_buffers);
|
client.add_model_request_handler(Self::handle_reload_buffers);
|
||||||
|
client.add_model_request_handler(Self::handle_get_permalink_to_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a buffer store, optionally retaining its buffers.
|
/// Creates a buffer store, optionally retaining its buffers.
|
||||||
|
@ -1170,6 +1172,78 @@ impl BufferStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_permalink_to_line(
|
||||||
|
&self,
|
||||||
|
buffer: &Model<Buffer>,
|
||||||
|
selection: Range<u32>,
|
||||||
|
cx: &AppContext,
|
||||||
|
) -> Task<Result<url::Url>> {
|
||||||
|
let buffer = buffer.read(cx);
|
||||||
|
let Some(file) = File::from_dyn(buffer.file()) else {
|
||||||
|
return Task::ready(Err(anyhow!("buffer has no file")));
|
||||||
|
};
|
||||||
|
|
||||||
|
match file.worktree.clone().read(cx) {
|
||||||
|
Worktree::Local(worktree) => {
|
||||||
|
let Some(repo) = worktree.local_git_repo(file.path()) else {
|
||||||
|
return Task::ready(Err(anyhow!("no repository for buffer found")));
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = file.path().clone();
|
||||||
|
|
||||||
|
cx.spawn(|cx| async move {
|
||||||
|
const REMOTE_NAME: &str = "origin";
|
||||||
|
let origin_url = repo
|
||||||
|
.remote_url(REMOTE_NAME)
|
||||||
|
.ok_or_else(|| anyhow!("remote \"{REMOTE_NAME}\" not found"))?;
|
||||||
|
|
||||||
|
let sha = repo
|
||||||
|
.head_sha()
|
||||||
|
.ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
|
||||||
|
|
||||||
|
let provider_registry =
|
||||||
|
cx.update(GitHostingProviderRegistry::default_global)?;
|
||||||
|
|
||||||
|
let (provider, remote) =
|
||||||
|
parse_git_remote_url(provider_registry, &origin_url)
|
||||||
|
.ok_or_else(|| anyhow!("failed to parse Git remote URL"))?;
|
||||||
|
|
||||||
|
let path = path
|
||||||
|
.to_str()
|
||||||
|
.context("failed to convert buffer path to string")?;
|
||||||
|
|
||||||
|
Ok(provider.build_permalink(
|
||||||
|
remote,
|
||||||
|
BuildPermalinkParams {
|
||||||
|
sha: &sha,
|
||||||
|
path,
|
||||||
|
selection: Some(selection),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Worktree::Remote(worktree) => {
|
||||||
|
let buffer_id = buffer.remote_id();
|
||||||
|
let project_id = worktree.project_id();
|
||||||
|
let client = worktree.client();
|
||||||
|
cx.spawn(|_| async move {
|
||||||
|
let response = client
|
||||||
|
.request(proto::GetPermalinkToLine {
|
||||||
|
project_id,
|
||||||
|
buffer_id: buffer_id.into(),
|
||||||
|
selection: Some(proto::Range {
|
||||||
|
start: selection.start as u64,
|
||||||
|
end: selection.end as u64,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
url::Url::parse(&response.permalink).context("failed to parse permalink")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn add_buffer(&mut self, buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Result<()> {
|
fn add_buffer(&mut self, buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Result<()> {
|
||||||
let remote_id = buffer.read(cx).remote_id();
|
let remote_id = buffer.read(cx).remote_id();
|
||||||
let is_remote = buffer.read(cx).replica_id() != 0;
|
let is_remote = buffer.read(cx).replica_id() != 0;
|
||||||
|
@ -1775,6 +1849,31 @@ impl BufferStore {
|
||||||
Ok(serialize_blame_buffer_response(blame))
|
Ok(serialize_blame_buffer_response(blame))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_get_permalink_to_line(
|
||||||
|
this: Model<Self>,
|
||||||
|
envelope: TypedEnvelope<proto::GetPermalinkToLine>,
|
||||||
|
mut cx: AsyncAppContext,
|
||||||
|
) -> Result<proto::GetPermalinkToLineResponse> {
|
||||||
|
let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
|
||||||
|
// let version = deserialize_version(&envelope.payload.version);
|
||||||
|
let selection = {
|
||||||
|
let proto_selection = envelope
|
||||||
|
.payload
|
||||||
|
.selection
|
||||||
|
.context("no selection to get permalink for defined")?;
|
||||||
|
proto_selection.start as u32..proto_selection.end as u32
|
||||||
|
};
|
||||||
|
let buffer = this.read_with(&cx, |this, _| this.get_existing(buffer_id))??;
|
||||||
|
let permalink = this
|
||||||
|
.update(&mut cx, |this, cx| {
|
||||||
|
this.get_permalink_to_line(&buffer, selection, cx)
|
||||||
|
})?
|
||||||
|
.await?;
|
||||||
|
Ok(proto::GetPermalinkToLineResponse {
|
||||||
|
permalink: permalink.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn wait_for_loading_buffer(
|
pub async fn wait_for_loading_buffer(
|
||||||
mut receiver: postage::watch::Receiver<Option<Result<Model<Buffer>, Arc<anyhow::Error>>>>,
|
mut receiver: postage::watch::Receiver<Option<Result<Model<Buffer>, Arc<anyhow::Error>>>>,
|
||||||
) -> Result<Model<Buffer>, Arc<anyhow::Error>> {
|
) -> Result<Model<Buffer>, Arc<anyhow::Error>> {
|
||||||
|
|
|
@ -3463,6 +3463,17 @@ impl Project {
|
||||||
self.buffer_store.read(cx).blame_buffer(buffer, version, cx)
|
self.buffer_store.read(cx).blame_buffer(buffer, version, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_permalink_to_line(
|
||||||
|
&self,
|
||||||
|
buffer: &Model<Buffer>,
|
||||||
|
selection: Range<u32>,
|
||||||
|
cx: &AppContext,
|
||||||
|
) -> Task<Result<url::Url>> {
|
||||||
|
self.buffer_store
|
||||||
|
.read(cx)
|
||||||
|
.get_permalink_to_line(buffer, selection, cx)
|
||||||
|
}
|
||||||
|
|
||||||
// RPC message handlers
|
// RPC message handlers
|
||||||
|
|
||||||
async fn handle_unshare_project(
|
async fn handle_unshare_project(
|
||||||
|
|
|
@ -292,7 +292,10 @@ message Envelope {
|
||||||
Toast toast = 261;
|
Toast toast = 261;
|
||||||
HideToast hide_toast = 262;
|
HideToast hide_toast = 262;
|
||||||
|
|
||||||
OpenServerSettings open_server_settings = 263; // current max
|
OpenServerSettings open_server_settings = 263;
|
||||||
|
|
||||||
|
GetPermalinkToLine get_permalink_to_line = 264;
|
||||||
|
GetPermalinkToLineResponse get_permalink_to_line_response = 265; // current max
|
||||||
}
|
}
|
||||||
|
|
||||||
reserved 87 to 88;
|
reserved 87 to 88;
|
||||||
|
@ -2508,3 +2511,13 @@ message HideToast {
|
||||||
message OpenServerSettings {
|
message OpenServerSettings {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetPermalinkToLine {
|
||||||
|
uint64 project_id = 1;
|
||||||
|
uint64 buffer_id = 2;
|
||||||
|
Range selection = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetPermalinkToLineResponse {
|
||||||
|
string permalink = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -370,6 +370,8 @@ messages!(
|
||||||
(Toast, Background),
|
(Toast, Background),
|
||||||
(HideToast, Background),
|
(HideToast, Background),
|
||||||
(OpenServerSettings, Foreground),
|
(OpenServerSettings, Foreground),
|
||||||
|
(GetPermalinkToLine, Foreground),
|
||||||
|
(GetPermalinkToLineResponse, Foreground),
|
||||||
);
|
);
|
||||||
|
|
||||||
request_messages!(
|
request_messages!(
|
||||||
|
@ -494,7 +496,8 @@ request_messages!(
|
||||||
(CheckFileExists, CheckFileExistsResponse),
|
(CheckFileExists, CheckFileExistsResponse),
|
||||||
(ShutdownRemoteServer, Ack),
|
(ShutdownRemoteServer, Ack),
|
||||||
(RemoveWorktree, Ack),
|
(RemoveWorktree, Ack),
|
||||||
(OpenServerSettings, OpenBufferResponse)
|
(OpenServerSettings, OpenBufferResponse),
|
||||||
|
(GetPermalinkToLine, GetPermalinkToLineResponse),
|
||||||
);
|
);
|
||||||
|
|
||||||
entity_messages!(
|
entity_messages!(
|
||||||
|
@ -571,7 +574,7 @@ entity_messages!(
|
||||||
Toast,
|
Toast,
|
||||||
HideToast,
|
HideToast,
|
||||||
OpenServerSettings,
|
OpenServerSettings,
|
||||||
|
GetPermalinkToLine,
|
||||||
);
|
);
|
||||||
|
|
||||||
entity_messages!(
|
entity_messages!(
|
||||||
|
|
|
@ -30,6 +30,8 @@ client.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
git.workspace = true
|
||||||
|
git_hosting_providers.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
http_client.workspace = true
|
http_client.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
|
|
|
@ -5,6 +5,7 @@ use client::ProxySettings;
|
||||||
use fs::{Fs, RealFs};
|
use fs::{Fs, RealFs};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
use futures::{select, select_biased, AsyncRead, AsyncWrite, AsyncWriteExt, FutureExt, SinkExt};
|
use futures::{select, select_biased, AsyncRead, AsyncWrite, AsyncWriteExt, FutureExt, SinkExt};
|
||||||
|
use git::GitHostingProviderRegistry;
|
||||||
use gpui::{AppContext, Context as _, ModelContext, UpdateGlobal as _};
|
use gpui::{AppContext, Context as _, ModelContext, UpdateGlobal as _};
|
||||||
use http_client::{read_proxy_from_env, Uri};
|
use http_client::{read_proxy_from_env, Uri};
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
|
@ -313,6 +314,8 @@ pub fn execute_run(
|
||||||
let listeners = ServerListeners::new(stdin_socket, stdout_socket, stderr_socket)?;
|
let listeners = ServerListeners::new(stdin_socket, stdout_socket, stderr_socket)?;
|
||||||
|
|
||||||
log::info!("starting headless gpui app");
|
log::info!("starting headless gpui app");
|
||||||
|
|
||||||
|
let git_hosting_provider_registry = Arc::new(GitHostingProviderRegistry::new());
|
||||||
gpui::App::headless().run(move |cx| {
|
gpui::App::headless().run(move |cx| {
|
||||||
settings::init(cx);
|
settings::init(cx);
|
||||||
HeadlessProject::init(cx);
|
HeadlessProject::init(cx);
|
||||||
|
@ -322,6 +325,9 @@ pub fn execute_run(
|
||||||
|
|
||||||
client::init_settings(cx);
|
client::init_settings(cx);
|
||||||
|
|
||||||
|
GitHostingProviderRegistry::set_global(git_hosting_provider_registry, cx);
|
||||||
|
git_hosting_providers::init(cx);
|
||||||
|
|
||||||
let project = cx.new_model(|cx| {
|
let project = cx.new_model(|cx| {
|
||||||
let fs = Arc::new(RealFs::new(Default::default(), None));
|
let fs = Arc::new(RealFs::new(Default::default(), None));
|
||||||
let node_settings_rx = initialize_settings(session.clone(), fs.clone(), cx);
|
let node_settings_rx = initialize_settings(session.clone(), fs.clone(), cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue