Merge branch 'main' into auto-update
5
.gitignore
vendored
@ -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
|
||||
|
@ -1 +1 @@
|
||||
collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "Kethku"]
|
||||
collaborators = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler", "gibusu", "Kethku"]
|
||||
|
634
Cargo.lock
generated
14
Dockerfile
@ -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"]
|
||||
|
@ -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"]
|
||||
|
2
Procfile
@ -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
|
||||
|
@ -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
|
||||
|
Before Width: | Height: | Size: 879 B After Width: | Height: | Size: 879 B |
Before Width: | Height: | Size: 979 B After Width: | Height: | Size: 979 B |
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 464 B |
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 499 B |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 284 B |
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 512 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 445 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 776 B After Width: | Height: | Size: 776 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 733 B After Width: | Height: | Size: 733 B |
Before Width: | Height: | Size: 676 B After Width: | Height: | Size: 676 B |
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 322 B |
264
assets/keymaps/default.json
Normal 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
@ -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
1338
assets/themes/light.json
Normal file
14
crates/assets/Cargo.toml
Normal 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"] }
|
||||
|
@ -3,7 +3,7 @@ use gpui::AssetSource;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "assets"]
|
||||
#[folder = "../../assets"]
|
||||
#[exclude = "*.DS_Store"]
|
||||
pub struct Assets;
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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" }
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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" }
|
||||
|
@ -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
@ -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
@ -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
@ -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))
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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| {
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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"
|
@ -1,2 +1,2 @@
|
||||
web: ./target/release/zed-server
|
||||
collab: ./target/release/collab
|
||||
release: ./target/release/sqlx migrate run
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@ -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.
|
@ -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())
|
@ -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
|
@ -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!(
|
@ -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();
|