Skip to content

Commit

Permalink
feat: allow resolving quality to a commit id
Browse files Browse the repository at this point in the history
Fixes #179
  • Loading branch information
connor4312 committed Apr 11, 2022
1 parent 6968fc1 commit 2b4fed0
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 39 deletions.
11 changes: 10 additions & 1 deletion src/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub struct ServeArgs {
pub struct InstallArgs {
/// Install specified commit ID of VS Code
#[clap(long)]
pub commit_id: String,
pub commit_id: Option<String>,

/// VS Code quality
#[clap(arg_enum, default_value = "stable")]
Expand All @@ -94,6 +94,15 @@ pub enum Quality {
Insiders,
}

impl Quality {
pub fn download_quality(&self) -> &'static str {
match self {
Quality::Insiders => "insider",
Quality::Stable => "stable",
}
}
}

impl fmt::Display for Quality {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expand Down
32 changes: 7 additions & 25 deletions src/cli/src/code_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
*--------------------------------------------------------------------------------------------*/

use crate::cli::Quality;
use crate::launcher::ServerParams;
use crate::launcher::ResolvedServerParams;
use crate::log;
use crate::state::{LauncherPaths, ServerPaths};
use crate::util::command::capture_command;
use crate::util::errors::{
wrap, AnyError, ExtensionInstallFailed, InvalidServerExtensionError, MissingEntrypointError,
StatusError, WrappedError,
};
use crate::util::version::PLATFORM_DOWNLOAD_PATH;
use crate::util::{http, sync};
use crate::util::{tar, zipper};
use lazy_static::lazy_static;
Expand Down Expand Up @@ -109,30 +110,11 @@ async fn download_server(
quality: Quality,
log: &log::Logger,
) -> Result<PathBuf, AnyError> {
let platform_download_path = if cfg!(all(target_os = "linux", target_arch = "x86_64")) {
"server-linux-x64"
} else if cfg!(all(target_os = "linux", target_arch = "armhf")) {
"server-linux-armhf"
} else if cfg!(all(target_os = "linux", target_arch = "arm64")) {
"server-linux-arm64"
} else if cfg!(target_os = "macos") {
"server-darwin"
} else if cfg!(all(target_os = "windows", target_arch = "x64")) {
"server-win32-x64"
} else if cfg!(target_os = "windows") {
"server-win32"
} else {
panic!("Your platform or architecture isn't supported!");
};

let quality_path = match quality {
Quality::Insiders => "insider",
Quality::Stable => "stable",
};

let download_url = format!(
"https://update.code.visualstudio.com/commit:{}/{}/{}",
commit_id, platform_download_path, quality_path
commit_id,
PLATFORM_DOWNLOAD_PATH,
quality.download_quality()
);

let response = reqwest::get(download_url).await?;
Expand Down Expand Up @@ -192,7 +174,7 @@ fn install_server(compressed_file: &Path, paths: &ServerPaths) -> Result<(), Any
}

pub async fn find_running_server(
server_params: &ServerParams,
server_params: &ResolvedServerParams,
launcher_paths: &LauncherPaths,
log: &log::Logger,
) -> Result<Option<CodeServer>, AnyError> {
Expand Down Expand Up @@ -261,7 +243,7 @@ async fn do_extension_install_on_running_server(

pub struct StartServerParams<'a> {
pub logger: &'a log::Logger,
pub server_params: &'a ServerParams,
pub server_params: &'a ResolvedServerParams,
pub launcher_paths: &'a LauncherPaths,
}

Expand Down
72 changes: 66 additions & 6 deletions src/cli/src/launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/

use std::time::Duration;

use crate::basis::{Basis, BasisTunnel, BasisTunnelDetails};
use crate::cli;
use crate::cli::Quality;
use crate::code_server::CodeServer;
use crate::log;
use crate::state::LauncherPaths;
use crate::util::errors::{AnyError, MismatchConnectionToken};
use crate::util::errors::{AnyError, MismatchConnectionToken, StatusError};
use crate::util::machine::process_exists;
use crate::util::version::PLATFORM_DOWNLOAD_PATH;
use crate::{code_server, code_server::StartServerParams};
use opentelemetry::KeyValue;
use serde::{Deserialize, Serialize};
use std::time::Duration;
use tokio::time;

#[derive(Serialize, Deserialize, Debug)]
pub struct ServerParams {
pub struct ServerParamsRaw {
pub commit_id: Option<String>,
pub quality: Quality,
pub connection_token: String,
pub port: String,
pub telemetry_level: String,
pub extensions: Vec<String>,
pub server_listen_flag: String,
}

pub struct ResolvedServerParams {
pub commit_id: String,
pub quality: Quality,
pub connection_token: String,
Expand All @@ -28,18 +38,68 @@ pub struct ServerParams {
pub server_listen_flag: String,
}

impl ServerParamsRaw {
pub async fn resolve(self, log: &log::Logger) -> Result<ResolvedServerParams, AnyError> {
Ok(ResolvedServerParams {
commit_id: self.get_or_fetch_commit_id(log).await?,
quality: self.quality,
connection_token: self.connection_token,
port: self.port,
telemetry_level: self.telemetry_level,
extensions: self.extensions,
server_listen_flag: self.server_listen_flag,
})
}

async fn get_or_fetch_commit_id(&self, log: &log::Logger) -> Result<String, AnyError> {
if let Some(c) = &self.commit_id {
return Ok(c.to_string());
}

let download_url = format!(
"https://update.code.visualstudio.com/api/latest/{}/{}",
PLATFORM_DOWNLOAD_PATH,
self.quality.download_quality()
);

let response = log::spanf!(
log,
log.span("server.version.resolve"),
reqwest::get(download_url)
)?;

if !response.status().is_success() {
return Err(StatusError::from_res(response).await?.into());
}

let version = response.json::<UpdateServerVersion>().await?.version;
log::verbose!(log, "Resolved quality {} to {}", self.quality, version);
Ok(version)
}
}

#[derive(Serialize, Deserialize, Debug)]
pub struct SuccessParams {
pub listening_port: u32,
pub connection_token: String,
pub tunnel: Option<BasisTunnelDetails>,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
struct UpdateServerVersion {
pub name: String,
pub version: String,
pub product_version: String,
pub timestamp: i64,
}

pub async fn install_and_start_server(
logger: &log::Logger,
basis: &mut Basis,
launcher_paths: &LauncherPaths,
server_params: &ServerParams,
server_params: &ResolvedServerParams,
tunnel_args: &cli::BasisDetails,
) -> Result<SuccessParams, AnyError> {
code_server::setup_server(
Expand Down Expand Up @@ -108,7 +168,7 @@ async fn forward_server(
server: CodeServer,
basis: &mut Basis,
launcher_paths: &LauncherPaths,
server_params: &ServerParams,
server_params: &ResolvedServerParams,
tunnel_args: &cli::BasisDetails,
) -> Result<BasisTunnelDetails, AnyError> {
let paths = launcher_paths.server_paths(server_params.quality, &server_params.commit_id);
Expand Down
6 changes: 4 additions & 2 deletions src/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,17 @@ async fn run_command(
log::spanf!(log, log.span("prereq"), PreReqChecker::new().verify())?;

let mut basis = Basis::new(log, launcher_paths);
let params = launcher::ServerParams {
let params = launcher::ServerParamsRaw {
commit_id: install_args.commit_id.to_owned(),
quality: install_args.quality,
port: String::from("0"),
telemetry_level: String::from("off"),
extensions: [].to_vec(),
server_listen_flag: String::from(""),
connection_token: format!("{}", Uuid::new_v4()),
};
}
.resolve(log)
.await?;

let success = launcher::install_and_start_server(
log,
Expand Down
11 changes: 6 additions & 5 deletions src/cli/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*--------------------------------------------------------------------------------------------*/

use crate::basis::Basis;
use crate::launcher::{ServerParams, SuccessParams};
use crate::launcher::{ServerParamsRaw, SuccessParams};
use crate::state::{prune_stopped_servers, LauncherPaths};
use crate::update::Update;
use crate::util::errors::{wrap, AnyError};
Expand All @@ -20,7 +20,7 @@ use tokio::sync::mpsc;
#[serde(tag = "method", content = "params")]
#[allow(non_camel_case_types)]
enum RequestMethod {
serve(launcher::ServerParams),
serve(launcher::ServerParamsRaw),
prune,
update(UpdateParams),
}
Expand Down Expand Up @@ -195,7 +195,7 @@ async fn process_socket(ctx: &mut HandlerContext, socket: TcpStream) -> Result<(
}

let response = match req.params {
RequestMethod::serve(p) => tj!("serve", handle_serve(ctx, &log, &p)),
RequestMethod::serve(p) => tj!("serve", handle_serve(ctx, &log, p)),
RequestMethod::prune => tj!("prune", handle_prune(ctx)),
RequestMethod::update(p) => tj!("update", handle_update(ctx, &p)),
};
Expand All @@ -218,13 +218,14 @@ async fn process_socket(ctx: &mut HandlerContext, socket: TcpStream) -> Result<(
async fn handle_serve(
ctx: &mut HandlerContext,
log: &log::Logger,
params: &ServerParams,
params: ServerParamsRaw,
) -> Result<SuccessParams, AnyError> {
let resolved = params.resolve(log).await?;
let success = launcher::install_and_start_server(
log,
&mut ctx.basis,
&ctx.launcher_paths,
params,
&resolved,
&ctx.serve_args.tunnel,
)
.await?;
Expand Down
16 changes: 16 additions & 0 deletions src/cli/src/util/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,19 @@ pub const LAUNCHER_VERSION: Option<&'static str> = option_env!("LAUNCHER_VERSION
pub const LAUNCHER_ASSET_NAME: Option<&'static str> = option_env!("LAUNCHER_ASSET_NAME");
pub const LAUNCHER_AI_KEY: Option<&'static str> = option_env!("LAUNCHER_AI_KEY");
pub const LAUNCHER_AI_ENDPOINT: Option<&'static str> = option_env!("LAUNCHER_AI_ENDPOINT");

pub const PLATFORM_DOWNLOAD_PATH: &str = if cfg!(all(target_os = "linux", target_arch = "x86_64")) {
"server-linux-x64"
} else if cfg!(all(target_os = "linux", target_arch = "armhf")) {
"server-linux-armhf"
} else if cfg!(all(target_os = "linux", target_arch = "arm64")) {
"server-linux-arm64"
} else if cfg!(target_os = "macos") {
"server-darwin"
} else if cfg!(all(target_os = "windows", target_arch = "x64")) {
"server-win32-x64"
} else if cfg!(target_os = "windows") {
"server-win32"
} else {
panic!("Your platform or architecture isn't supported!");
};

0 comments on commit 2b4fed0

Please sign in to comment.