forked from gitpod-io/openvscode-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cli: add acquire_cli (microsoft#179837)
* cli: add acquire_cli As given in my draft document, pipes a CLI of the given platform to the specified process, for example: ```js const cmd = await rpc.call('acquire_cli', { command: 'node', args: [ '-e', 'process.stdin.pipe(fs.createWriteStream("c:/users/conno/downloads/hello-cli"))', ], platform: Platform.LinuxX64, quality: 'insider', }); ``` It genericizes caching so that the CLI is also cached on the host, just like servers. * fix bug
- Loading branch information
1 parent
24c4407
commit f743297
Showing
15 changed files
with
487 additions
and
403 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
use std::{ | ||
fs::create_dir_all, | ||
path::{Path, PathBuf}, | ||
}; | ||
|
||
use futures::Future; | ||
use tokio::fs::remove_dir_all; | ||
|
||
use crate::{ | ||
state::PersistedState, | ||
util::errors::{wrap, AnyError, WrappedError}, | ||
}; | ||
|
||
const KEEP_LRU: usize = 5; | ||
const STAGING_SUFFIX: &str = ".staging"; | ||
|
||
#[derive(Clone)] | ||
pub struct DownloadCache { | ||
path: PathBuf, | ||
state: PersistedState<Vec<String>>, | ||
} | ||
|
||
impl DownloadCache { | ||
pub fn new(path: PathBuf) -> DownloadCache { | ||
DownloadCache { | ||
state: PersistedState::new(path.join("lru.json")), | ||
path, | ||
} | ||
} | ||
|
||
/// Gets the download cache path. Names of cache entries can be formed by | ||
/// joining them to the path. | ||
pub fn path(&self) -> &Path { | ||
&self.path | ||
} | ||
|
||
/// Gets whether a cache exists with the name already. Marks it as recently | ||
/// used if it does exist. | ||
pub fn exists(&self, name: &str) -> Option<PathBuf> { | ||
let p = self.path.join(name); | ||
if !p.exists() { | ||
return None; | ||
} | ||
|
||
let _ = self.touch(name.to_string()); | ||
Some(p) | ||
} | ||
|
||
/// Removes the item from the cache, if it exists | ||
pub fn delete(&self, name: &str) -> Result<(), WrappedError> { | ||
let f = self.path.join(name); | ||
if f.exists() { | ||
std::fs::remove_dir_all(f).map_err(|e| wrap(e, "error removing cached folder"))?; | ||
} | ||
|
||
self.state.update(|l| { | ||
l.retain(|n| n != name); | ||
}) | ||
} | ||
|
||
/// Calls the function to create the cached folder if it doesn't exist, | ||
/// returning the path where the folder is. Note that the path passed to | ||
/// the `do_create` method is a staging path and will not be the same as the | ||
/// final returned path. | ||
pub async fn create<F, T>( | ||
&self, | ||
name: impl AsRef<str>, | ||
do_create: F, | ||
) -> Result<PathBuf, AnyError> | ||
where | ||
F: FnOnce(PathBuf) -> T, | ||
T: Future<Output = Result<(), AnyError>> + Send, | ||
{ | ||
let name = name.as_ref(); | ||
let target_dir = self.path.join(name); | ||
if target_dir.exists() { | ||
return Ok(target_dir); | ||
} | ||
|
||
let temp_dir = self.path.join(format!("{}{}", name, STAGING_SUFFIX)); | ||
let _ = remove_dir_all(&temp_dir).await; // cleanup any existing | ||
|
||
create_dir_all(&temp_dir).map_err(|e| wrap(e, "error creating server directory"))?; | ||
do_create(temp_dir.clone()).await?; | ||
|
||
let _ = self.touch(name.to_string()); | ||
std::fs::rename(&temp_dir, &target_dir) | ||
.map_err(|e| wrap(e, "error renaming downloaded server"))?; | ||
|
||
Ok(target_dir) | ||
} | ||
|
||
fn touch(&self, name: String) -> Result<(), AnyError> { | ||
self.state.update(|l| { | ||
if let Some(index) = l.iter().position(|s| s == &name) { | ||
l.remove(index); | ||
} | ||
l.insert(0, name); | ||
|
||
if l.len() <= KEEP_LRU { | ||
return; | ||
} | ||
|
||
if let Some(f) = l.last() { | ||
let f = self.path.join(f); | ||
if !f.exists() || std::fs::remove_dir_all(f).is_ok() { | ||
l.pop(); | ||
} | ||
} | ||
})?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.