mirror of
https://github.com/pesde-pkg/pesde.git
synced 2025-05-04 10:33:47 +01:00
feat: add PESDE_HOME variable
Adds the PESDE_HOME env variable to allow changing where pesde will store data like engines, bins, etc. to support e.g. small OS disks & large data disks.
This commit is contained in:
parent
398763a171
commit
6aeedd8602
7 changed files with 62 additions and 54 deletions
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
- Add dev only installs in #32 by @Stefanuk12
|
- Add dev only installs in #32 by @Stefanuk12
|
||||||
|
- Add `PESDE_HOME` variable (defaults to $HOME/.pesde) to override pesde's directory's location by @daimond113
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Download engines in install step rather than lazily by @daimond113
|
- Download engines in install step rather than lazily by @daimond113
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::cli::{
|
use crate::cli::{
|
||||||
style::{ADDED_STYLE, CLI_STYLE},
|
style::{ADDED_STYLE, CLI_STYLE},
|
||||||
version::replace_pesde_bin_exe,
|
version::replace_pesde_bin_exe,
|
||||||
HOME_DIR,
|
|
||||||
};
|
};
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
|
@ -25,16 +24,18 @@ impl SelfInstallCommand {
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use windows_registry::CURRENT_USER;
|
use windows_registry::CURRENT_USER;
|
||||||
|
|
||||||
let bin_dir = crate::cli::bin_dir().await?;
|
let bin_dir = crate::cli::bin_dir()?;
|
||||||
|
|
||||||
let env = CURRENT_USER
|
let env = CURRENT_USER
|
||||||
.create("Environment")
|
.create("Environment")
|
||||||
.context("failed to open Environment key")?;
|
.context("failed to open Environment key")?;
|
||||||
let path = env.get_string("Path").context("failed to get Path value")?;
|
let path = env.get_string("Path").context("failed to get Path value")?;
|
||||||
|
|
||||||
let bin_dir = bin_dir.to_string_lossy();
|
let bin_dir = bin_dir
|
||||||
|
.to_str()
|
||||||
|
.context("bin directory path contains invalid characters")?;
|
||||||
|
|
||||||
let exists = path.split(';').any(|part| *part == bin_dir);
|
let exists = path.split(';').any(|part| part == bin_dir);
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
let new_path = format!("{path};{bin_dir}");
|
let new_path = format!("{path};{bin_dir}");
|
||||||
|
@ -43,7 +44,7 @@ impl SelfInstallCommand {
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"\nin order to allow proper functionality {} was added to PATH.\n\n{}",
|
"\nin order to allow proper functionality {} was added to PATH.\n\n{}",
|
||||||
style(format!("`~/{HOME_DIR}/bin`")).green(),
|
style(format!("`{bin_dir}`")).green(),
|
||||||
WARN_STYLE.apply_to("please restart your shell for this to take effect")
|
WARN_STYLE.apply_to("please restart your shell for this to take effect")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::cli::{auth::Tokens, home_dir};
|
use crate::cli::auth::Tokens;
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use fs_err::tokio as fs;
|
use fs_err::tokio as fs;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use super::config_path;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct CliConfig {
|
pub struct CliConfig {
|
||||||
|
@ -33,7 +35,7 @@ impl Default for CliConfig {
|
||||||
|
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn read_config() -> anyhow::Result<CliConfig> {
|
pub async fn read_config() -> anyhow::Result<CliConfig> {
|
||||||
let config_string = match fs::read_to_string(home_dir()?.join("config.toml")).await {
|
let config_string = match fs::read_to_string(config_path()?).await {
|
||||||
Ok(config_string) => config_string,
|
Ok(config_string) => config_string,
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||||
return Ok(CliConfig::default());
|
return Ok(CliConfig::default());
|
||||||
|
@ -49,7 +51,7 @@ pub async fn read_config() -> anyhow::Result<CliConfig> {
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn write_config(config: &CliConfig) -> anyhow::Result<()> {
|
pub async fn write_config(config: &CliConfig) -> anyhow::Result<()> {
|
||||||
let config_string = toml::to_string(config).context("failed to serialize config")?;
|
let config_string = toml::to_string(config).context("failed to serialize config")?;
|
||||||
fs::write(home_dir()?.join("config.toml"), config_string)
|
fs::write(config_path()?, config_string)
|
||||||
.await
|
.await
|
||||||
.context("failed to write config file")?;
|
.context("failed to write config file")?;
|
||||||
|
|
||||||
|
|
|
@ -301,8 +301,11 @@ pub async fn install(
|
||||||
root_progress.set_message("download");
|
root_progress.set_message("download");
|
||||||
root_progress.set_style(reporters::root_progress_style_with_progress());
|
root_progress.set_style(reporters::root_progress_style_with_progress());
|
||||||
|
|
||||||
|
let bin_dir = bin_dir()?;
|
||||||
|
fs::create_dir_all(&bin_dir).await.context("failed to create bin directory")?;
|
||||||
|
|
||||||
let hooks = InstallHooks {
|
let hooks = InstallHooks {
|
||||||
bin_folder: bin_dir().await?,
|
bin_folder: bin_dir,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::cli::{
|
||||||
style::{ERROR_STYLE, INFO_STYLE, WARN_STYLE},
|
style::{ERROR_STYLE, INFO_STYLE, WARN_STYLE},
|
||||||
};
|
};
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use fs_err::tokio as fs;
|
|
||||||
use futures::StreamExt as _;
|
use futures::StreamExt as _;
|
||||||
use pesde::{
|
use pesde::{
|
||||||
errors::ManifestReadError,
|
errors::ManifestReadError,
|
||||||
|
@ -39,20 +38,31 @@ pub mod style;
|
||||||
#[cfg(feature = "version-management")]
|
#[cfg(feature = "version-management")]
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|
||||||
pub const HOME_DIR: &str = concat!(".", env!("CARGO_PKG_NAME"));
|
pub const PESDE_DIR: &str = concat!(".", env!("CARGO_PKG_NAME"));
|
||||||
|
|
||||||
pub fn home_dir() -> anyhow::Result<PathBuf> {
|
fn base_dir() -> anyhow::Result<PathBuf> {
|
||||||
Ok(dirs::home_dir()
|
Ok(match std::env::var("PESDE_HOME") {
|
||||||
|
Ok(base) => PathBuf::from(base),
|
||||||
|
_ => dirs::home_dir()
|
||||||
.context("failed to get home directory")?
|
.context("failed to get home directory")?
|
||||||
.join(HOME_DIR))
|
.join(PESDE_DIR),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn bin_dir() -> anyhow::Result<PathBuf> {
|
pub fn bin_dir() -> anyhow::Result<PathBuf> {
|
||||||
let bin_dir = home_dir()?.join("bin");
|
Ok(base_dir()?.join("bin"))
|
||||||
fs::create_dir_all(&bin_dir)
|
}
|
||||||
.await
|
|
||||||
.context("failed to create bin folder")?;
|
pub fn engines_dir() -> anyhow::Result<PathBuf> {
|
||||||
Ok(bin_dir)
|
Ok(base_dir()?.join("engines"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config_path() -> anyhow::Result<PathBuf> {
|
||||||
|
Ok(base_dir()?.join("config.toml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_dir() -> anyhow::Result<PathBuf> {
|
||||||
|
Ok(base_dir()?.join("data"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_overrides(
|
pub fn resolve_overrides(
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
||||||
bin_dir,
|
bin_dir,
|
||||||
config::{read_config, write_config, CliConfig},
|
config::{read_config, write_config, CliConfig},
|
||||||
files::make_executable,
|
files::make_executable,
|
||||||
home_dir,
|
|
||||||
style::{ADDED_STYLE, CLI_STYLE, REMOVED_STYLE, URL_STYLE},
|
style::{ADDED_STYLE, CLI_STYLE, REMOVED_STYLE, URL_STYLE},
|
||||||
},
|
},
|
||||||
util::no_build_metadata,
|
util::no_build_metadata,
|
||||||
|
@ -32,6 +31,8 @@ use std::{
|
||||||
};
|
};
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use super::engines_dir;
|
||||||
|
|
||||||
pub fn current_version() -> Version {
|
pub fn current_version() -> Version {
|
||||||
Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
|
Version::parse(env!("CARGO_PKG_VERSION")).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -115,12 +116,10 @@ pub async fn check_for_updates(reqwest: &reqwest::Client) -> anyhow::Result<()>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const ENGINES_DIR: &str = "engines";
|
|
||||||
|
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
async fn get_installed_versions(engine: EngineKind) -> anyhow::Result<BTreeSet<Version>> {
|
async fn get_installed_versions(engine: EngineKind) -> anyhow::Result<BTreeSet<Version>> {
|
||||||
let source = engine.source();
|
let source = engine.source();
|
||||||
let path = home_dir()?.join(ENGINES_DIR).join(source.directory());
|
let path = engines_dir()?.join(source.directory());
|
||||||
let mut installed_versions = BTreeSet::new();
|
let mut installed_versions = BTreeSet::new();
|
||||||
|
|
||||||
let mut read_dir = match fs::read_dir(&path).await {
|
let mut read_dir = match fs::read_dir(&path).await {
|
||||||
|
@ -152,7 +151,7 @@ pub async fn get_or_download_engine(
|
||||||
reporter: Arc<impl DownloadsReporter>,
|
reporter: Arc<impl DownloadsReporter>,
|
||||||
) -> anyhow::Result<(PathBuf, Version)> {
|
) -> anyhow::Result<(PathBuf, Version)> {
|
||||||
let source = engine.source();
|
let source = engine.source();
|
||||||
let path = home_dir()?.join(ENGINES_DIR).join(source.directory());
|
let path = engines_dir()?.join(source.directory());
|
||||||
|
|
||||||
let installed_versions = get_installed_versions(engine).await?;
|
let installed_versions = get_installed_versions(engine).await?;
|
||||||
|
|
||||||
|
@ -229,8 +228,7 @@ pub async fn get_or_download_engine(
|
||||||
|
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn replace_pesde_bin_exe(with: &Path) -> anyhow::Result<()> {
|
pub async fn replace_pesde_bin_exe(with: &Path) -> anyhow::Result<()> {
|
||||||
let bin_exe_path = bin_dir()
|
let bin_exe_path = bin_dir()?
|
||||||
.await?
|
|
||||||
.join(EngineKind::Pesde.to_string())
|
.join(EngineKind::Pesde.to_string())
|
||||||
.with_extension(std::env::consts::EXE_EXTENSION);
|
.with_extension(std::env::consts::EXE_EXTENSION);
|
||||||
|
|
||||||
|
@ -255,6 +253,12 @@ pub async fn replace_pesde_bin_exe(with: &Path) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(parent) = bin_exe_path.parent() {
|
||||||
|
fs::create_dir_all(parent)
|
||||||
|
.await
|
||||||
|
.context("failed to create bin directory")?;
|
||||||
|
}
|
||||||
|
|
||||||
fs::copy(with, &bin_exe_path)
|
fs::copy(with, &bin_exe_path)
|
||||||
.await
|
.await
|
||||||
.context("failed to copy executable to bin folder")?;
|
.context("failed to copy executable to bin folder")?;
|
||||||
|
@ -264,14 +268,19 @@ pub async fn replace_pesde_bin_exe(with: &Path) -> anyhow::Result<()> {
|
||||||
|
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
pub async fn make_linker_if_needed(engine: EngineKind) -> anyhow::Result<()> {
|
pub async fn make_linker_if_needed(engine: EngineKind) -> anyhow::Result<()> {
|
||||||
let bin_dir = bin_dir().await?;
|
let linker = bin_dir()?
|
||||||
let linker = bin_dir
|
|
||||||
.join(engine.to_string())
|
.join(engine.to_string())
|
||||||
.with_extension(std::env::consts::EXE_EXTENSION);
|
.with_extension(std::env::consts::EXE_EXTENSION);
|
||||||
|
|
||||||
if fs::metadata(&linker).await.is_err() {
|
if fs::metadata(&linker).await.is_err() {
|
||||||
let exe = current_exe().context("failed to get current exe path")?;
|
let exe = current_exe().context("failed to get current exe path")?;
|
||||||
|
|
||||||
|
if let Some(parent) = linker.parent() {
|
||||||
|
fs::create_dir_all(parent)
|
||||||
|
.await
|
||||||
|
.context("failed to create linker directory")?;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let result = fs::symlink_file(exe, linker);
|
let result = fs::symlink_file(exe, linker);
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -1,8 +1,9 @@
|
||||||
#[cfg(feature = "version-management")]
|
#[cfg(feature = "version-management")]
|
||||||
use crate::cli::version::{check_for_updates, current_version, get_or_download_engine};
|
use crate::cli::version::{check_for_updates, current_version, get_or_download_engine};
|
||||||
use crate::cli::{auth::get_tokens, display_err, home_dir, style::ERROR_STYLE, HOME_DIR};
|
use crate::cli::{auth::get_tokens, display_err, style::ERROR_STYLE, PESDE_DIR};
|
||||||
use anyhow::Context as _;
|
use anyhow::Context as _;
|
||||||
use clap::{builder::styling::AnsiColor, Parser};
|
use clap::{builder::styling::AnsiColor, Parser};
|
||||||
|
use cli::data_dir;
|
||||||
use fs_err::tokio as fs;
|
use fs_err::tokio as fs;
|
||||||
use indicatif::MultiProgress;
|
use indicatif::MultiProgress;
|
||||||
use pesde::{
|
use pesde::{
|
||||||
|
@ -207,15 +208,6 @@ async fn run() -> anyhow::Result<()> {
|
||||||
if bin_folder.file_name().is_some_and(|parent| parent != "bin") {
|
if bin_folder.file_name().is_some_and(|parent| parent != "bin") {
|
||||||
break 'scripts;
|
break 'scripts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we're not in {path}/.pesde/bin/{exe}
|
|
||||||
if bin_folder
|
|
||||||
.parent()
|
|
||||||
.and_then(|home_folder| home_folder.file_name())
|
|
||||||
.is_some_and(|home_folder| home_folder != HOME_DIR)
|
|
||||||
{
|
|
||||||
break 'scripts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let linker_file_name = format!("{exe_name}.bin.luau");
|
let linker_file_name = format!("{exe_name}.bin.luau");
|
||||||
|
@ -287,19 +279,9 @@ async fn run() -> anyhow::Result<()> {
|
||||||
std::process::exit(status.code().unwrap_or(1i32));
|
std::process::exit(status.code().unwrap_or(1i32));
|
||||||
};
|
};
|
||||||
|
|
||||||
let home_dir = home_dir()?;
|
let cas_dir = get_linkable_dir(&project_root_dir)
|
||||||
let data_dir = home_dir.join("data");
|
|
||||||
fs::create_dir_all(&data_dir)
|
|
||||||
.await
|
.await
|
||||||
.expect("failed to create data directory");
|
.join(PESDE_DIR)
|
||||||
|
|
||||||
let cas_dir = get_linkable_dir(&project_root_dir).await.join(HOME_DIR);
|
|
||||||
|
|
||||||
let cas_dir = if cas_dir == home_dir {
|
|
||||||
&data_dir
|
|
||||||
} else {
|
|
||||||
&cas_dir
|
|
||||||
}
|
|
||||||
.join("cas");
|
.join("cas");
|
||||||
|
|
||||||
tracing::debug!("using cas dir in {}", cas_dir.display());
|
tracing::debug!("using cas dir in {}", cas_dir.display());
|
||||||
|
@ -307,7 +289,7 @@ async fn run() -> anyhow::Result<()> {
|
||||||
let project = Project::new(
|
let project = Project::new(
|
||||||
project_root_dir,
|
project_root_dir,
|
||||||
project_workspace_dir,
|
project_workspace_dir,
|
||||||
data_dir,
|
data_dir()?,
|
||||||
cas_dir,
|
cas_dir,
|
||||||
AuthConfig::new().with_tokens(get_tokens().await?.0),
|
AuthConfig::new().with_tokens(get_tokens().await?.0),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Reference in a new issue