Merge branch 'main' into auto-update

This commit is contained in:
Antonio Scandurra 2022-04-21 09:45:28 +02:00
commit fb87bacc7e
341 changed files with 21713 additions and 5967 deletions

5
.gitignore vendored
View File

@ -2,6 +2,7 @@
/zed.xcworkspace
.DS_Store
/script/node_modules
/crates/server/.env.toml
/crates/server/static/styles.css
/styles/node_modules
/crates/collab/.env.toml
/crates/collab/static/styles.css
/vendor/bin

View File

@ -1 +1 @@
collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "Kethku"]
collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "gibusu", "Kethku"]

634
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -14,20 +14,20 @@ RUN --mount=type=cache,target=./script/node_modules \
RUN --mount=type=cache,target=./script/node_modules \
script/build-css --release
# Compile server
# Compile collab server
RUN --mount=type=cache,target=./script/node_modules \
--mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=./target \
cargo build --release --package zed-server --bin zed-server
cargo build --release --package collab --bin collab
# Copy server binary out of cached directory
# Copy collab server binary out of cached directory
RUN --mount=type=cache,target=./target \
cp /app/target/release/zed-server /app/zed-server
cp /app/target/release/collab /app/collab
# Copy server binary to the runtime image
# Copy collab server binary to the runtime image
FROM debian:bullseye-slim as runtime
RUN apt-get update; \
apt-get install -y --no-install-recommends libcurl4-openssl-dev ca-certificates
WORKDIR app
COPY --from=builder /app/zed-server /app
ENTRYPOINT ["/app/zed-server"]
COPY --from=builder /app/collab /app
ENTRYPOINT ["/app/collab"]

View File

@ -11,5 +11,5 @@ RUN apt-get update; \
apt-get install -y --no-install-recommends libssl1.1
WORKDIR app
COPY --from=builder /app/bin/sqlx /app
COPY ./server/migrations /app/migrations
COPY ./collab/migrations /app/migrations
ENTRYPOINT ["/app/sqlx", "migrate", "run"]

View File

@ -1,2 +1,2 @@
web: cd ../zed.dev && PORT=3000 npx next dev
collab: cd crates/server && cargo run
collab: cd crates/collab && cargo run

View File

@ -23,7 +23,7 @@ script/sqlx migrate run
script/seed-db
```
Run `zed.dev` and the collaboration server.
Run the web frontend and the collaboration server.
```
brew install foreman

View File

Before

Width:  |  Height:  |  Size: 879 B

After

Width:  |  Height:  |  Size: 879 B

View File

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 979 B

View File

Before

Width:  |  Height:  |  Size: 464 B

After

Width:  |  Height:  |  Size: 464 B

View File

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 499 B

View File

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 317 B

View File

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 284 B

View File

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 512 B

View File

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 516 B

View File

Before

Width:  |  Height:  |  Size: 445 B

After

Width:  |  Height:  |  Size: 445 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 776 B

After

Width:  |  Height:  |  Size: 776 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 733 B

After

Width:  |  Height:  |  Size: 733 B

View File

Before

Width:  |  Height:  |  Size: 676 B

After

Width:  |  Height:  |  Size: 676 B

View File

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 322 B

264
assets/keymaps/default.json Normal file
View File

@ -0,0 +1,264 @@
{
"*": {
"ctrl-alt-cmd-f": "workspace::FollowNextCollaborator",
"cmd-s": "workspace::Save",
"cmd-alt-i": "zed::DebugElements",
"cmd-k cmd-left": "workspace::ActivatePreviousPane",
"cmd-k cmd-right": "workspace::ActivateNextPane",
"cmd-=": "zed::IncreaseBufferFontSize",
"cmd--": "zed::DecreaseBufferFontSize",
"cmd-,": "zed::OpenSettings"
},
"menu": {
"up": "menu::SelectPrev",
"ctrl-p": "menu::SelectPrev",
"down": "menu::SelectNext",
"ctrl-n": "menu::SelectNext",
"cmd-up": "menu::SelectFirst",
"cmd-down": "menu::SelectLast",
"enter": "menu::Confirm",
"escape": "menu::Cancel"
},
"Pane": {
"shift-cmd-{": "pane::ActivatePrevItem",
"shift-cmd-}": "pane::ActivateNextItem",
"cmd-w": "pane::CloseActiveItem",
"alt-cmd-w": "pane::CloseInactiveItems",
"ctrl--": "pane::GoBack",
"shift-ctrl-_": "pane::GoForward",
"cmd-k up": [
"pane::Split",
"Up"
],
"cmd-k down": [
"pane::Split",
"Down"
],
"cmd-k left": [
"pane::Split",
"Left"
],
"cmd-k right": [
"pane::Split",
"Right"
],
"cmd-shift-F": "project_search::ToggleFocus",
"cmd-f": "project_search::ToggleFocus",
"cmd-g": "search::SelectNextMatch",
"cmd-shift-G": "search::SelectPrevMatch"
},
"Workspace": {
"cmd-shift-F": "project_search::Deploy",
"cmd-k cmd-t": "theme_selector::Toggle",
"cmd-k t": "theme_selector::Reload",
"cmd-t": "project_symbols::Toggle",
"cmd-p": "file_finder::Toggle",
"cmd-shift-P": "command_palette::Toggle",
"alt-shift-D": "diagnostics::Deploy",
"ctrl-alt-cmd-j": "journal::NewJournalEntry",
"cmd-1": [
"workspace::ToggleSidebarItemFocus",
{
"side": "Left",
"item_index": 0
}
],
"cmd-shift-!": [
"workspace::ToggleSidebarItem",
{
"side": "Left",
"item_index": 0
}
]
},
"ProjectSearchBar": {
"enter": "project_search::Search",
"cmd-enter": "project_search::SearchInNew"
},
"BufferSearchBar": {
"escape": "buffer_search::Dismiss",
"cmd-f": "buffer_search::FocusEditor",
"enter": "search::SelectNextMatch",
"shift-enter": "search::SelectPrevMatch"
},
"Editor": {
"escape": "editor::Cancel",
"backspace": "editor::Backspace",
"ctrl-h": "editor::Backspace",
"delete": "editor::Delete",
"ctrl-d": "editor::Delete",
"tab": "editor::Tab",
"shift-tab": "editor::TabPrev",
"cmd-[": "editor::Outdent",
"cmd-]": "editor::Indent",
"ctrl-shift-K": "editor::DeleteLine",
"alt-backspace": "editor::DeleteToPreviousWordStart",
"alt-h": "editor::DeleteToPreviousWordStart",
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
"ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",
"alt-delete": "editor::DeleteToNextWordEnd",
"alt-d": "editor::DeleteToNextWordEnd",
"ctrl-alt-delete": "editor::DeleteToNextSubwordEnd",
"ctrl-alt-d": "editor::DeleteToNextSubwordEnd",
"cmd-backspace": "editor::DeleteToBeginningOfLine",
"cmd-delete": "editor::DeleteToEndOfLine",
"ctrl-k": "editor::CutToEndOfLine",
"cmd-shift-D": "editor::DuplicateLine",
"ctrl-cmd-up": "editor::MoveLineUp",
"ctrl-cmd-down": "editor::MoveLineDown",
"cmd-x": "editor::Cut",
"cmd-c": "editor::Copy",
"cmd-v": "editor::Paste",
"cmd-z": "editor::Undo",
"cmd-shift-Z": "editor::Redo",
"up": "editor::MoveUp",
"down": "editor::MoveDown",
"left": "editor::MoveLeft",
"right": "editor::MoveRight",
"ctrl-p": "editor::MoveUp",
"ctrl-n": "editor::MoveDown",
"ctrl-b": "editor::MoveLeft",
"ctrl-f": "editor::MoveRight",
"alt-left": "editor::MoveToPreviousWordStart",
"alt-b": "editor::MoveToPreviousWordStart",
"ctrl-alt-left": "editor::MoveToPreviousSubwordStart",
"ctrl-alt-b": "editor::MoveToPreviousSubwordStart",
"alt-right": "editor::MoveToNextWordEnd",
"alt-f": "editor::MoveToNextWordEnd",
"ctrl-alt-right": "editor::MoveToNextSubwordEnd",
"ctrl-alt-f": "editor::MoveToNextSubwordEnd",
"cmd-left": "editor::MoveToBeginningOfLine",
"ctrl-a": "editor::MoveToBeginningOfLine",
"cmd-right": "editor::MoveToEndOfLine",
"ctrl-e": "editor::MoveToEndOfLine",
"cmd-up": "editor::MoveToBeginning",
"cmd-down": "editor::MoveToEnd",
"shift-up": "editor::SelectUp",
"ctrl-shift-P": "editor::SelectUp",
"shift-down": "editor::SelectDown",
"ctrl-shift-N": "editor::SelectDown",
"shift-left": "editor::SelectLeft",
"ctrl-shift-B": "editor::SelectLeft",
"shift-right": "editor::SelectRight",
"ctrl-shift-F": "editor::SelectRight",
"alt-shift-left": "editor::SelectToPreviousWordStart",
"alt-shift-B": "editor::SelectToPreviousWordStart",
"ctrl-alt-shift-left": "editor::SelectToPreviousSubwordStart",
"ctrl-alt-shift-B": "editor::SelectToPreviousSubwordStart",
"alt-shift-right": "editor::SelectToNextWordEnd",
"alt-shift-F": "editor::SelectToNextWordEnd",
"ctrl-alt-shift-right": "editor::SelectToNextSubwordEnd",
"cmd-shift-up": "editor::SelectToBeginning",
"cmd-shift-down": "editor::SelectToEnd",
"cmd-a": "editor::SelectAll",
"cmd-l": "editor::SelectLine",
"cmd-shift-L": "editor::SplitSelectionIntoLines",
"cmd-alt-up": "editor::AddSelectionAbove",
"cmd-ctrl-p": "editor::AddSelectionAbove",
"cmd-alt-down": "editor::AddSelectionBelow",
"cmd-ctrl-n": "editor::AddSelectionBelow",
"ctrl-alt-shift-F": "editor::SelectToNextSubwordEnd",
"cmd-shift-left": [
"editor::SelectToBeginningOfLine",
{
"stop_at_soft_wraps": true
}
],
"ctrl-shift-A": [
"editor::SelectToBeginningOfLine",
{
"stop_at_soft_wraps": true
}
],
"cmd-shift-right": [
"editor::SelectToEndOfLine",
{
"stop_at_soft_wraps": true
}
],
"ctrl-shift-E": [
"editor::SelectToEndOfLine",
{
"stop_at_soft_wraps": true
}
],
"cmd-d": [
"editor::SelectNext",
{
"replace_newest": false
}
],
"cmd-k cmd-d": [
"editor::SelectNext",
{
"replace_newest": true
}
],
"cmd-/": "editor::ToggleComments",
"alt-up": "editor::SelectLargerSyntaxNode",
"ctrl-w": "editor::SelectLargerSyntaxNode",
"alt-down": "editor::SelectSmallerSyntaxNode",
"ctrl-shift-W": "editor::SelectSmallerSyntaxNode",
"cmd-u": "editor::UndoSelection",
"cmd-shift-U": "editor::RedoSelection",
"f8": "editor::GoToNextDiagnostic",
"shift-f8": "editor::GoToPrevDiagnostic",
"f2": "editor::Rename",
"f12": "editor::GoToDefinition",
"alt-shift-f12": "editor::FindAllReferences",
"ctrl-m": "editor::MoveToEnclosingBracket",
"pageup": "editor::PageUp",
"pagedown": "editor::PageDown",
"alt-cmd-[": "editor::Fold",
"alt-cmd-]": "editor::UnfoldLines",
"alt-cmd-f": "editor::FoldSelectedRanges",
"ctrl-space": "editor::ShowCompletions",
"cmd-.": "editor::ToggleCodeActions",
"alt-enter": "editor::OpenExcerpts",
"cmd-f10": "editor::RestartLanguageServer"
},
"Editor && renaming": {
"enter": "editor::ConfirmRename"
},
"Editor && showing_completions": {
"enter": "editor::ConfirmCompletion",
"tab": "editor::ConfirmCompletion"
},
"Editor && showing_code_actions": {
"enter": "editor::ConfirmCodeAction"
},
"Editor && mode == full": {
"enter": "editor::Newline",
"cmd-f": [
"buffer_search::Deploy",
{
"focus": true
}
],
"cmd-e": [
"buffer_search::Deploy",
{
"focus": false
}
],
"cmd-shift-O": "outline::Toggle",
"ctrl-g": "go_to_line::Toggle"
},
"Editor && mode == auto_height": {
"alt-enter": [
"editor::Input",
"\n"
]
},
"GoToLine": {
"escape": "go_to_line::Toggle",
"enter": "go_to_line::Confirm"
},
"ChatPanel": {
"enter": "chat_panel::Send"
},
"ProjectPanel": {
"left": "project_panel::CollapseSelectedEntry",
"right": "project_panel::ExpandSelectedEntry"
}
}

93
assets/keymaps/vim.json Normal file
View File

@ -0,0 +1,93 @@
{
"Editor && VimControl": {
"i": [
"vim::SwitchMode",
"Insert"
],
"g": [
"vim::PushOperator",
{
"Namespace": "G"
}
],
"h": "vim::Left",
"j": "vim::Down",
"k": "vim::Up",
"l": "vim::Right",
"0": "vim::StartOfLine",
"shift-$": "vim::EndOfLine",
"shift-G": "vim::EndOfDocument",
"w": "vim::NextWordStart",
"shift-W": [
"vim::NextWordStart",
{
"ignorePunctuation": true
}
],
"e": "vim::NextWordEnd",
"shift-E": [
"vim::NextWordEnd",
{
"ignorePunctuation": true
}
],
"b": "vim::PreviousWordStart",
"shift-B": [
"vim::PreviousWordStart",
{
"ignorePunctuation": true
}
],
"escape": [
"vim::SwitchMode",
"Normal"
]
},
"Editor && vim_operator == g": {
"g": "vim::StartOfDocument"
},
"Editor && vim_mode == insert": {
"escape": "vim::NormalBefore",
"ctrl-c": "vim::NormalBefore"
},
"Editor && vim_mode == normal": {
"c": [
"vim::PushOperator",
"Change"
],
"d": [
"vim::PushOperator",
"Delete"
]
},
"Editor && vim_operator == c": {
"w": [
"vim::NextWordEnd",
{
"ignorePunctuation": false
}
],
"shift-W": [
"vim::NextWordEnd",
{
"ignorePunctuation": true
}
]
},
"Editor && vim_operator == d": {
"w": [
"vim::NextWordStart",
{
"ignorePunctuation": false,
"stopAtNewline": true
}
],
"shift-W": [
"vim::NextWordStart",
{
"ignorePunctuation": true,
"stopAtNewline": true
}
]
}
}

1338
assets/themes/dark.json Normal file

File diff suppressed because it is too large Load Diff

1338
assets/themes/light.json Normal file

File diff suppressed because it is too large Load Diff

14
crates/assets/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "assets"
version = "0.1.0"
edition = "2021"
[lib]
path = "src/assets.rs"
doctest = false
[dependencies]
gpui = { path = "../gpui" }
anyhow = "1.0.38"
rust-embed = { version = "6.3", features = ["include-exclude"] }

View File

@ -3,7 +3,7 @@ use gpui::AssetSource;
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "assets"]
#[folder = "../../assets"]
#[exclude = "*.DS_Store"]
pub struct Assets;

View File

@ -8,9 +8,10 @@ path = "src/auto_update.rs"
doctest = false
[dependencies]
gpui = { path = "../gpui" }
theme = { path = "../theme" }
client = { path = "../client" }
gpui = { path = "../gpui" }
settings = { path = "../settings" }
theme = { path = "../theme" }
workspace = { path = "../workspace" }
anyhow = "1.0.38"
lazy_static = "1.4"

View File

@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use client::http::{self, HttpClient};
use gpui::{
action,
actions,
elements::{Empty, MouseEventHandler, Text},
platform::AppVersion,
AsyncAppContext, Element, Entity, ModelContext, ModelHandle, MutableAppContext, Task, View,
@ -9,10 +9,11 @@ use gpui::{
};
use lazy_static::lazy_static;
use serde::Deserialize;
use settings::Settings;
use smol::{fs::File, io::AsyncReadExt, process::Command};
use std::{env, ffi::OsString, path::PathBuf, sync::Arc, time::Duration};
use surf::Request;
use workspace::{ItemHandle, Settings, StatusItemView};
use workspace::{ItemHandle, StatusItemView};
const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60);
const ACCESS_TOKEN: &'static str = "618033988749894";
@ -24,6 +25,8 @@ lazy_static! {
pub static ref ZED_APP_PATH: Option<PathBuf> = env::var("ZED_APP_PATH").ok().map(PathBuf::from);
}
actions!(auto_update, [Check, DismissErrorMessage]);
#[derive(Clone, PartialEq, Eq)]
pub enum AutoUpdateStatus {
Idle,
@ -46,8 +49,6 @@ pub struct AutoUpdateIndicator {
updater: Option<ModelHandle<AutoUpdater>>,
}
action!(DismissErrorMessage);
#[derive(Deserialize)]
struct JsonRelease {
version: String,
@ -66,16 +67,15 @@ pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut Mutab
updater
});
cx.set_global(Some(auto_updater));
cx.add_global_action(|_: &Check, cx| {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
}
});
cx.add_action(AutoUpdateIndicator::dismiss_error_message);
}
}
pub fn check(cx: &mut MutableAppContext) {
if let Some(updater) = AutoUpdater::get(cx) {
updater.update(cx, |updater, cx| updater.poll(cx));
}
}
impl AutoUpdater {
fn get(cx: &mut MutableAppContext) -> Option<ModelHandle<Self>> {
cx.default_global::<Option<ModelHandle<Self>>>().clone()

View File

@ -14,6 +14,7 @@ gpui = { path = "../gpui" }
language = { path = "../language" }
project = { path = "../project" }
search = { path = "../search" }
settings = { path = "../settings" }
theme = { path = "../theme" }
workspace = { path = "../workspace" }

View File

@ -6,8 +6,9 @@ use gpui::{
use language::{Buffer, OutlineItem};
use project::Project;
use search::ProjectSearchView;
use settings::Settings;
use theme::SyntaxTheme;
use workspace::{ItemHandle, Settings, ToolbarItemLocation, ToolbarItemView};
use workspace::{ItemHandle, ToolbarItemLocation, ToolbarItemView};
pub enum Event {
UpdateLocation,

View File

@ -11,6 +11,7 @@ doctest = false
client = { path = "../client" }
editor = { path = "../editor" }
gpui = { path = "../gpui" }
settings = { path = "../settings" }
theme = { path = "../theme" }
util = { path = "../util" }
workspace = { path = "../workspace" }

View File

@ -4,19 +4,18 @@ use client::{
};
use editor::Editor;
use gpui::{
action,
actions,
elements::*,
keymap::Binding,
platform::CursorStyle,
views::{ItemType, Select, SelectStyle},
AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View,
ViewContext, ViewHandle,
};
use postage::prelude::Stream;
use settings::{Settings, SoftWrap};
use std::sync::Arc;
use time::{OffsetDateTime, UtcOffset};
use util::{ResultExt, TryFutureExt};
use workspace::{settings::SoftWrap, Settings};
const MESSAGE_LOADING_THRESHOLD: usize = 50;
@ -33,14 +32,11 @@ pub struct ChatPanel {
pub enum Event {}
action!(Send);
action!(LoadMoreMessages);
actions!(chat_panel, [Send, LoadMoreMessages]);
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ChatPanel::send);
cx.add_action(ChatPanel::load_more_messages);
cx.add_bindings(vec![Binding::new("enter", Send, Some("ChatPanel"))]);
}
impl ChatPanel {

24
crates/cli/Cargo.toml Normal file
View File

@ -0,0 +1,24 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2021"
[lib]
path = "src/cli.rs"
doctest = false
[[bin]]
name = "cli"
path = "src/main.rs"
[dependencies]
anyhow = "1.0"
clap = { version = "3.1", features = ["derive"] }
dirs = "3.0"
ipc-channel = "0.16"
serde = { version = "1.0", features = ["derive"] }
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"
core-services = "0.2"
plist = "1.3"

22
crates/cli/src/cli.rs Normal file
View File

@ -0,0 +1,22 @@
pub use ipc_channel::ipc;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Serialize, Deserialize)]
pub struct IpcHandshake {
pub requests: ipc::IpcSender<CliRequest>,
pub responses: ipc::IpcReceiver<CliResponse>,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum CliRequest {
Open { paths: Vec<PathBuf>, wait: bool },
}
#[derive(Debug, Serialize, Deserialize)]
pub enum CliResponse {
Ping,
Stdout { message: String },
Stderr { message: String },
Exit { status: i32 },
}

124
crates/cli/src/main.rs Normal file
View File

@ -0,0 +1,124 @@
use anyhow::{anyhow, Result};
use clap::Parser;
use cli::{CliRequest, CliResponse, IpcHandshake};
use core_foundation::{
array::{CFArray, CFIndex},
string::kCFStringEncodingUTF8,
url::{CFURLCreateWithBytes, CFURL},
};
use core_services::{kLSLaunchDefaults, LSLaunchURLSpec, LSOpenFromURLSpec, TCFType};
use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender};
use serde::Deserialize;
use std::{ffi::OsStr, fs, path::PathBuf, ptr};
#[derive(Parser)]
#[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))]
struct Args {
/// Wait for all of the given paths to be closed before exiting.
#[clap(short, long)]
wait: bool,
/// A sequence of space-separated paths that you want to open.
#[clap()]
paths: Vec<PathBuf>,
/// Print Zed's version and the app path.
#[clap(short, long)]
version: bool,
/// Custom Zed.app path
#[clap(short, long)]
bundle_path: Option<PathBuf>,
}
#[derive(Debug, Deserialize)]
struct InfoPlist {
#[serde(rename = "CFBundleShortVersionString")]
bundle_short_version_string: String,
}
fn main() -> Result<()> {
let args = Args::parse();
let bundle_path = if let Some(bundle_path) = args.bundle_path {
bundle_path.canonicalize()?
} else {
locate_bundle()?
};
if args.version {
let plist_path = bundle_path.join("Contents/Info.plist");
let plist = plist::from_file::<_, InfoPlist>(plist_path)?;
println!(
"Zed {} {}",
plist.bundle_short_version_string,
bundle_path.to_string_lossy()
);
return Ok(());
}
let (tx, rx) = launch_app(bundle_path)?;
tx.send(CliRequest::Open {
paths: args
.paths
.into_iter()
.map(|path| fs::canonicalize(path).map_err(|error| anyhow!(error)))
.collect::<Result<Vec<PathBuf>>>()?,
wait: args.wait,
})?;
while let Ok(response) = rx.recv() {
match response {
CliResponse::Ping => {}
CliResponse::Stdout { message } => println!("{message}"),
CliResponse::Stderr { message } => eprintln!("{message}"),
CliResponse::Exit { status } => std::process::exit(status),
}
}
Ok(())
}
fn locate_bundle() -> Result<PathBuf> {
let cli_path = std::env::current_exe()?.canonicalize()?;
let mut app_path = cli_path.clone();
while app_path.extension() != Some(OsStr::new("app")) {
if !app_path.pop() {
return Err(anyhow!("cannot find app bundle containing {:?}", cli_path));
}
}
Ok(app_path)
}
fn launch_app(app_path: PathBuf) -> Result<(IpcSender<CliRequest>, IpcReceiver<CliResponse>)> {
let (server, server_name) = IpcOneShotServer::<IpcHandshake>::new()?;
let url = format!("zed-cli://{server_name}");
let status = unsafe {
let app_url =
CFURL::from_path(&app_path, true).ok_or_else(|| anyhow!("invalid app path"))?;
let url_to_open = CFURL::wrap_under_create_rule(CFURLCreateWithBytes(
ptr::null(),
url.as_ptr(),
url.len() as CFIndex,
kCFStringEncodingUTF8,
ptr::null(),
));
let urls_to_open = CFArray::from_copyable(&[url_to_open.as_concrete_TypeRef()]);
LSOpenFromURLSpec(
&LSLaunchURLSpec {
appURL: app_url.as_concrete_TypeRef(),
itemURLs: urls_to_open.as_concrete_TypeRef(),
passThruParams: ptr::null(),
launchFlags: kLSLaunchDefaults,
asyncRefCon: ptr::null_mut(),
},
ptr::null_mut(),
)
};
if status == 0 {
let (_, handshake) = server.accept()?;
Ok((handshake.requests, handshake.responses))
} else {
Err(anyhow!("cannot start {:?}", app_path))
}
}

View File

@ -21,7 +21,7 @@ async-tungstenite = { version = "0.16", features = ["async-tls"] }
futures = "0.3"
image = "0.23"
lazy_static = "1.4.0"
log = "0.4"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
parking_lot = "0.11.1"
postage = { version = "0.4.1", features = ["futures-traits"] }
rand = "0.8.3"

View File

@ -13,7 +13,7 @@ use async_tungstenite::tungstenite::{
};
use futures::{future::LocalBoxFuture, FutureExt, StreamExt};
use gpui::{
action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext,
actions, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext,
Entity, ModelContext, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle,
};
use http::HttpClient;
@ -50,7 +50,7 @@ lazy_static! {
.and_then(|s| if s.is_empty() { None } else { Some(s) });
}
action!(Authenticate);
actions!(client, [Authenticate]);
pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) {
cx.add_global_action(move |_: &Authenticate, cx| {

View File

@ -6,7 +6,6 @@ use anyhow::{anyhow, Result};
use futures::{future::BoxFuture, stream::BoxStream, Future, StreamExt};
use gpui::{executor, ModelHandle, TestAppContext};
use parking_lot::Mutex;
use postage::barrier;
use rpc::{proto, ConnectionId, Peer, Receipt, TypedEnvelope};
use std::{fmt, rc::Rc, sync::Arc};
@ -23,7 +22,6 @@ struct FakeServerState {
connection_id: Option<ConnectionId>,
forbid_connections: bool,
auth_count: usize,
connection_killer: Option<barrier::Sender>,
access_token: usize,
}
@ -76,15 +74,13 @@ impl FakeServer {
Err(EstablishConnectionError::Unauthorized)?
}
let (client_conn, server_conn, kill) =
Connection::in_memory(cx.background());
let (client_conn, server_conn, _) = Connection::in_memory(cx.background());
let (connection_id, io, incoming) =
peer.add_test_connection(server_conn, cx.background()).await;
cx.background().spawn(io).detach();
let mut state = state.lock();
state.connection_id = Some(connection_id);
state.incoming = Some(incoming);
state.connection_killer = Some(kill);
Ok(client_conn)
})
}

View File

@ -1,12 +1,12 @@
[package]
authors = ["Nathan Sobo <nathan@warp.dev>"]
default-run = "zed-server"
default-run = "collab"
edition = "2021"
name = "zed-server"
name = "collab"
version = "0.1.0"
[[bin]]
name = "zed-server"
name = "collab"
[[bin]]
name = "seed"
@ -15,25 +15,27 @@ required-features = ["seed-support"]
[dependencies]
collections = { path = "../collections" }
rpc = { path = "../rpc" }
util = { path = "../util" }
anyhow = "1.0.40"
async-io = "1.3"
async-std = { version = "1.8.0", features = ["attributes"] }
async-trait = "0.1.50"
async-tungstenite = "0.16"
base64 = "0.13"
clap = "=3.0.0-beta.2"
clap = "3.1"
comrak = "0.10"
either = "1.6"
envy = "0.4.2"
futures = "0.3"
handlebars = "3.5"
http-auth-basic = "0.1.3"
json_env_logger = "0.1"
jwt-simple = "0.10.0"
lipsum = { version = "0.8", optional = true }
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
oauth2 = { version = "4.0.0", default_features = false }
oauth2-surf = "0.1.1"
parking_lot = "0.11.1"
postage = { version = "0.4.1", features = ["futures-traits"] }
rand = "0.8"
rust-embed = { version = "6.3", features = ["include-exclude"] }
scrypt = "0.7"
@ -64,6 +66,8 @@ editor = { path = "../editor", features = ["test-support"] }
language = { path = "../language", features = ["test-support"] }
lsp = { path = "../lsp", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
settings = { path = "../settings", features = ["test-support"] }
theme = { path = "../theme" }
workspace = { path = "../workspace", features = ["test-support"] }
ctor = "0.1"
env_logger = "0.8"

View File

@ -1,2 +1,2 @@
web: ./target/release/zed-server
collab: ./target/release/collab
release: ./target/release/sqlx migrate run

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -8,14 +8,14 @@ kind: Service
apiVersion: v1
metadata:
namespace: ${ZED_KUBE_NAMESPACE}
name: zed
name: collab
annotations:
service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
service.beta.kubernetes.io/do-loadbalancer-certificate-id: "2634d353-1ab4-437f-add2-4ffd8f315233"
service.beta.kubernetes.io/do-loadbalancer-certificate-id: "40879815-9a6b-4bbb-8207-8f2c7c0218f9"
spec:
type: LoadBalancer
selector:
app: zed
app: collab
ports:
- name: web
protocol: TCP
@ -26,19 +26,19 @@ apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${ZED_KUBE_NAMESPACE}
name: zed
name: collab
spec:
replicas: 1
selector:
matchLabels:
app: zed
app: collab
template:
metadata:
labels:
app: zed
app: collab
spec:
containers:
- name: zed
- name: collab
image: "${ZED_IMAGE_ID}"
ports:
- containerPort: 8080
@ -81,6 +81,10 @@ spec:
secretKeyRef:
name: api
key: token
- name: LOG_JSON
value: "1"
- name: RUST_LOG
value: "trace"
securityContext:
capabilities:
# FIXME - Switch to the more restrictive `PERFMON` capability.

View File

@ -111,7 +111,6 @@ async fn create_access_token(request: Request) -> tide::Result {
.get_user_by_github_login(request.param("github_login")?)
.await?
.ok_or_else(|| surf::Error::from_str(StatusCode::NotFound, "user not found"))?;
let access_token = auth::create_access_token(request.db().as_ref(), user.id).await?;
#[derive(Deserialize)]
struct QueryParams {
@ -123,9 +122,6 @@ async fn create_access_token(request: Request) -> tide::Result {
surf::Error::from_str(StatusCode::UnprocessableEntity, "invalid query params")
})?;
let encrypted_access_token =
auth::encrypt_access_token(&access_token, query_params.public_key.clone())?;
let mut user_id = user.id;
if let Some(impersonate) = query_params.impersonate {
if user.admin {
@ -151,6 +147,10 @@ async fn create_access_token(request: Request) -> tide::Result {
}
}
let access_token = auth::create_access_token(request.db().as_ref(), user_id).await?;
let encrypted_access_token =
auth::encrypt_access_token(&access_token, query_params.public_key.clone())?;
Ok(tide::Response::builder(StatusCode::Ok)
.body(json!({"user_id": user_id, "encrypted_access_token": encrypted_access_token}))
.build())

View File

@ -1,7 +1,8 @@
use crate::{AppState, Request, RequestExt as _};
use serde::Deserialize;
use log::as_serde;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tide::{http::mime, log, Server};
use tide::{http::mime, Server};
pub fn add_routes(app: &mut Server<Arc<AppState>>) {
app.at("/").get(get_home);
@ -18,7 +19,7 @@ async fn get_home(mut request: Request) -> tide::Result {
}
async fn post_signup(mut request: Request) -> tide::Result {
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Serialize)]
struct Form {
github_login: String,
email_address: String,
@ -38,7 +39,7 @@ async fn post_signup(mut request: Request) -> tide::Result {
.map(str::to_string)
.unwrap_or(form.github_login);
log::info!("Signup submitted: {:?}", form);
log::info!(form = as_serde!(form); "signup submitted");
// Save signup in the database
request

View File

@ -27,7 +27,7 @@ use rust_embed::RustEmbed;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use surf::http::cookies::SameSite;
use tide::{log, sessions::SessionMiddleware};
use tide::sessions::SessionMiddleware;
use tide_compress::CompressMiddleware;
type Request = tide::Request<Arc<AppState>>;
@ -138,7 +138,11 @@ struct LayoutData {
#[async_std::main]
async fn main() -> tide::Result<()> {
log::start();
if std::env::var("LOG_JSON").is_ok() {
json_env_logger::init();
} else {
tide::log::start();
}
if let Err(error) = env::load_dotenv() {
log::error!(

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,10 @@ pub struct JoinedProject<'a> {
pub project: &'a Project,
}
pub struct SharedProject {
pub authorized_user_ids: Vec<UserId>,
}
pub struct UnsharedProject {
pub connection_ids: Vec<ConnectionId>,
pub authorized_user_ids: Vec<UserId>,
@ -130,9 +134,6 @@ impl Store {
}
}
#[cfg(test)]
self.check_invariants();
Ok(result)
}
@ -244,6 +245,9 @@ impl Store {
language_servers: Default::default(),
},
);
if let Some(connection) = self.connections.get_mut(&host_connection_id) {
connection.projects.insert(project_id);
}
self.next_project_id += 1;
project_id
}
@ -266,16 +270,12 @@ impl Store {
.or_default()
.insert(project_id);
}
if let Some(connection) = self.connections.get_mut(&project.host_connection_id) {
connection.projects.insert(project_id);
}
project.worktrees.insert(worktree_id, worktree);
if let Ok(share) = project.share_mut() {
share.worktrees.insert(worktree_id, Default::default());
}
#[cfg(test)]
self.check_invariants();
Ok(())
} else {
Err(anyhow!("no such project"))?
@ -312,8 +312,6 @@ impl Store {
}
}
#[cfg(test)]
self.check_invariants();
Ok(project)
} else {
Err(anyhow!("no such project"))?
@ -358,13 +356,14 @@ impl Store {
}
}
#[cfg(test)]
self.check_invariants();
Ok((worktree, guest_connection_ids))
}
pub fn share_project(&mut self, project_id: u64, connection_id: ConnectionId) -> bool {
pub fn share_project(
&mut self,
project_id: u64,
connection_id: ConnectionId,
) -> tide::Result<SharedProject> {
if let Some(project) = self.projects.get_mut(&project_id) {
if project.host_connection_id == connection_id {
let mut share = ProjectShare::default();
@ -372,10 +371,12 @@ impl Store {
share.worktrees.insert(*worktree_id, Default::default());
}
project.share = Some(share);
return true;
return Ok(SharedProject {
authorized_user_ids: project.authorized_user_ids(),
});
}
}
false
Err(anyhow!("no such project"))?
}
pub fn unshare_project(
@ -402,9 +403,6 @@ impl Store {
}
}
#[cfg(test)]
self.check_invariants();
Ok(UnsharedProject {
connection_ids,
authorized_user_ids,
@ -490,9 +488,6 @@ impl Store {
share.active_replica_ids.insert(replica_id);
share.guests.insert(connection_id, (replica_id, user_id));
#[cfg(test)]
self.check_invariants();
Ok(JoinedProject {
replica_id,
project: &self.projects[&project_id],
@ -525,9 +520,6 @@ impl Store {
let connection_ids = project.connection_ids();
let authorized_user_ids = project.authorized_user_ids();
#[cfg(test)]
self.check_invariants();
Ok(LeftProject {
connection_ids,
authorized_user_ids,
@ -555,10 +547,6 @@ impl Store {
worktree.entries.insert(entry.id, entry.clone());
}
let connection_ids = project.connection_ids();
#[cfg(test)]
self.check_invariants();
Ok(connection_ids)
}
@ -632,7 +620,7 @@ impl Store {
}
#[cfg(test)]
fn check_invariants(&self) {
pub fn check_invariants(&self) {
for (connection_id, connection) in &self.connections {
for project_id in &connection.projects {
let project = &self.projects.get(&project_id).unwrap();

Some files were not shown because too many files have changed in this diff Show More