diff --git a/.changeset/fuzzy-terms-smile.md b/.changeset/fuzzy-terms-smile.md new file mode 100644 index 0000000..250074f --- /dev/null +++ b/.changeset/fuzzy-terms-smile.md @@ -0,0 +1,5 @@ +--- +"pactup": patch +--- + +Support XDG convention on MacOS diff --git a/.changeset/sixty-planets-dance.md b/.changeset/sixty-planets-dance.md new file mode 100644 index 0000000..e9cc75a --- /dev/null +++ b/.changeset/sixty-planets-dance.md @@ -0,0 +1,5 @@ +--- +"pactup": patch +--- + +align some fixes with fnm diff --git a/.github/workflows/release_pactup.yml b/.github/workflows/release_pactup.yml index a6684ce..e8e8acf 100644 --- a/.github/workflows/release_pactup.yml +++ b/.github/workflows/release_pactup.yml @@ -176,7 +176,9 @@ jobs: name: pactup v${{ needs.check.outputs.version }} tag_name: pactup_v${{ needs.check.outputs.version }} draft: true - files: pactup-* + files: | + pactup-*.tar.gz + pactup-*.zip fail_on_unmatched_files: true - name: wait 3 minutes for smoke test diff --git a/Cargo.toml b/Cargo.toml index 2db0c83..81058e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,12 +4,13 @@ version = "0.2.12" edition = "2021" license = "GPL-3.0" publish = true +build = "build.rs" repository = "https://github.com/kadena-community/pactup" description = "Fast and simple Pact version manager" [dependencies] anyhow = { version = "1.0", features = ["backtrace"] } -chrono = { version = "0.4", features = ["serde"] } +chrono = { version = "0.4", features = ["now", "serde"], default-features = false } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } reqwest = { version = "0.12", features = [ @@ -23,7 +24,7 @@ url = { version = "2.5", features = ["serde"] } clap = { version = "4.5", features = ["derive", "env"] } clap_complete = "4.5" colored = "2.0" -dirs = "5.0" +etcetera = "0.8" encoding_rs_io = "0.1" env_logger = "0.11" indoc = "2.0" @@ -41,19 +42,18 @@ flate2 = "1.0" walkdir = "2.5" indicatif = { version = "0.17", features = ["improved_unicode"] } - [dev-dependencies] pretty_assertions = "1.4" duct = "0.13" test-log = "0.2" http = "1.1" -# [build-dependencies] -# embed-resource = "2.4" +[build-dependencies] +embed-resource = "2.4" [target.'cfg(windows)'.dependencies] -csv = "1.2" -junction = "1.0" +csv = "1.3" +junction = "1.1" [profile.dev] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b82c150 --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + embed_resource::compile("manifest.rc", embed_resource::NONE); +} diff --git a/package.json b/package.json index 16898b3..ade5355 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "url": "git@github.com:kadena-community/pactup.git" }, "author": "Salama Ashoush ", - "packageManager": "pnpm@9.1.3", + "packageManager": "pnpm@9.1.4", "license": "GPLv3", "description": "Linter for the JavaScript Oxidation Compiler", "keywords": [ @@ -44,15 +44,15 @@ }, "devDependencies": { "@changesets/changelog-github": "0.5.0", - "@changesets/cli": "2.27.4", - "@types/node": "^20.12.12", + "@changesets/cli": "2.27.5", + "@types/node": "^20.13.0", "@types/shell-escape": "^0.2.3", "chalk": "^5.3.0", "cmd-ts": "0.13.0", "cross-env": "^7.0.3", "execa": "9.1.0", "lerna-changelog": "2.2.0", - "prettier": "3.2.5", + "prettier": "3.3.0", "pv": "1.0.1", "shell-escape": "^0.2.0", "svg-term-cli": "2.1.1", diff --git a/pactup-manifest.rc b/pactup-manifest.rc new file mode 100644 index 0000000..824565a --- /dev/null +++ b/pactup-manifest.rc @@ -0,0 +1,2 @@ +#define RT_MANIFEST 24 +1 RT_MANIFEST "pactup.manifest" diff --git a/pactup.manifest b/pactup.manifest new file mode 100644 index 0000000..4a2fe9d --- /dev/null +++ b/pactup.manifest @@ -0,0 +1,11 @@ + + + + + true + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88bdc83..bcf9eee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,11 +12,11 @@ importers: specifier: 0.5.0 version: 0.5.0(encoding@0.1.13) '@changesets/cli': - specifier: 2.27.4 - version: 2.27.4 + specifier: 2.27.5 + version: 2.27.5 '@types/node': - specifier: ^20.12.12 - version: 20.12.12 + specifier: ^20.13.0 + version: 20.13.0 '@types/shell-escape': specifier: ^0.2.3 version: 0.2.3 @@ -36,8 +36,8 @@ importers: specifier: 2.2.0 version: 2.2.0 prettier: - specifier: 3.2.5 - version: 3.2.5 + specifier: 3.3.0 + version: 3.3.0 pv: specifier: 1.0.1 version: 1.0.1 @@ -72,11 +72,11 @@ packages: resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==} engines: {node: '>=6.9.0'} - '@changesets/apply-release-plan@7.0.2': - resolution: {integrity: sha512-lRdN9c8e2zbzSWTGK3HzlNATPWETBy6tMvf4MENUzb7OQD3kFQ+dVKCJtj42pLWRjLn2flbLofEK04k92GEttg==} + '@changesets/apply-release-plan@7.0.3': + resolution: {integrity: sha512-klL6LCdmfbEe9oyfLxnidIf/stFXmrbFO/3gT5LU5pcyoZytzJe4gWpTBx3BPmyNPl16dZ1xrkcW7b98e3tYkA==} - '@changesets/assemble-release-plan@6.0.1': - resolution: {integrity: sha512-VXKjqGomnj4evJ/B6ENUFMxV+EV/LDkdWl2+8NjCcGo4Rn/aogjofCDLWbWEhtjtgLUdwvlsoydibIDOf/abvA==} + '@changesets/assemble-release-plan@6.0.2': + resolution: {integrity: sha512-n9/Tdq+ze+iUtjmq0mZO3pEhJTKkku9hUxtUadW30jlN7kONqJG3O6ALeXrmc6gsi/nvoCuKjqEJ68Hk8RbMTQ==} '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} @@ -84,24 +84,24 @@ packages: '@changesets/changelog-github@0.5.0': resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - '@changesets/cli@2.27.4': - resolution: {integrity: sha512-X3Nd9cBoyuykjmMJnRFHik26UoA5y4ikhds4BJE0IGKpnIvkV8gRqyZE6Tcmc3zuS5GXfCmGnyJXVwxe89uX5A==} + '@changesets/cli@2.27.5': + resolution: {integrity: sha512-UVppOvzCjjylBenFcwcZNG5IaZ8jsIaEVraV/pbXgukYNb0Oqa0d8UWb0LkYzA1Bf1HmUrOfccFcRLheRuA7pA==} hasBin: true - '@changesets/config@3.0.0': - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + '@changesets/config@3.0.1': + resolution: {integrity: sha512-nCr8pOemUjvGJ8aUu8TYVjqnUL+++bFOQHBVmtNbLvKzIDkN/uiP/Z4RKmr7NNaiujIURHySDEGFPftR4GbTUA==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - '@changesets/get-dependents-graph@2.0.0': - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + '@changesets/get-dependents-graph@2.1.0': + resolution: {integrity: sha512-QOt6pQq9RVXKGHPVvyKimJDYJumx7p4DO5MO9AhRJYgAPgv0emhNqAqqysSVKHBm4sxKlGN4S1zXOIb5yCFuhQ==} '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.1': - resolution: {integrity: sha512-1zojjyxeIzIHA/zWXZ3XYxKySBDtbTP9PS6EZLrM0r1luq8Oy7U0zBq/I9NX77qVJV9EF3cO4KP5pfRHorSLTg==} + '@changesets/get-release-plan@4.0.2': + resolution: {integrity: sha512-rOalz7nMuMV2vyeP7KBeAhqEB7FM2GFPO5RQSoOoUKKH9L6wW3QyPA2K+/rG9kBrWl2HckPVES73/AuwPvbH3w==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -383,8 +383,8 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@20.12.12': - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} + '@types/node@20.13.0': + resolution: {integrity: sha512-FM6AOb3khNkNIXPnHFDYaHerSv8uN22C91z098AnGccVu+Pcdhi+pNUFDi0iLmPIsVE0JBD0KVS7mzUYt4nRzQ==} '@types/node@8.10.66': resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} @@ -1625,8 +1625,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.0: + resolution: {integrity: sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==} engines: {node: '>=14'} hasBin: true @@ -2249,10 +2249,10 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 - '@changesets/apply-release-plan@7.0.2': + '@changesets/apply-release-plan@7.0.3': dependencies: '@babel/runtime': 7.24.6 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.1 '@changesets/get-version-range-type': 0.4.0 '@changesets/git': 3.0.0 '@changesets/should-skip-package': 0.1.0 @@ -2266,11 +2266,11 @@ snapshots: resolve-from: 5.0.0 semver: 7.6.2 - '@changesets/assemble-release-plan@6.0.1': + '@changesets/assemble-release-plan@6.0.2': dependencies: '@babel/runtime': 7.24.6 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.0 '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -2288,16 +2288,16 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.27.4': + '@changesets/cli@2.27.5': dependencies: '@babel/runtime': 7.24.6 - '@changesets/apply-release-plan': 7.0.2 - '@changesets/assemble-release-plan': 6.0.1 + '@changesets/apply-release-plan': 7.0.3 + '@changesets/assemble-release-plan': 6.0.2 '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.1 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.1 + '@changesets/get-dependents-graph': 2.1.0 + '@changesets/get-release-plan': 4.0.2 '@changesets/git': 3.0.0 '@changesets/logger': 0.1.0 '@changesets/pre': 2.0.0 @@ -2324,10 +2324,10 @@ snapshots: term-size: 2.2.1 tty-table: 4.2.3 - '@changesets/config@3.0.0': + '@changesets/config@3.0.1': dependencies: '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.0 '@changesets/logger': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -2338,7 +2338,7 @@ snapshots: dependencies: extendable-error: 0.1.7 - '@changesets/get-dependents-graph@2.0.0': + '@changesets/get-dependents-graph@2.1.0': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -2353,11 +2353,11 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.1': + '@changesets/get-release-plan@4.0.2': dependencies: '@babel/runtime': 7.24.6 - '@changesets/assemble-release-plan': 6.0.1 - '@changesets/config': 3.0.0 + '@changesets/assemble-release-plan': 6.0.2 + '@changesets/config': 3.0.1 '@changesets/pre': 2.0.0 '@changesets/read': 0.6.0 '@changesets/types': 6.0.0 @@ -2609,7 +2609,7 @@ snapshots: '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.12 + '@types/node': 20.13.0 '@types/globby@6.1.0': dependencies: @@ -2627,7 +2627,7 @@ snapshots: '@types/node@12.20.55': {} - '@types/node@20.12.12': + '@types/node@20.13.0': dependencies: undici-types: 5.26.5 @@ -3993,7 +3993,7 @@ snapshots: prettier@2.8.8: {} - prettier@3.2.5: {} + prettier@3.3.0: {} pretty-ms@9.0.0: dependencies: diff --git a/scripts/install.sh b/scripts/install.sh index 7a1f3d3..32c331b 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -176,29 +176,29 @@ setup_shell() { CONF_FILE=${ZDOTDIR:-$HOME}/.zshrc ensure_containing_dir_exists "$CONF_FILE" echo "Installing for Zsh. Appending the following to $CONF_FILE:" - echo "" - echo ' # pactup' - echo ' export PATH="'"$INSTALL_DIR"':$PATH"' - echo ' eval "`pactup env --use-on-cd`"' - - echo '' >>$CONF_FILE - echo '# pactup' >>$CONF_FILE - echo 'export PATH="'$INSTALL_DIR':$PATH"' >>$CONF_FILE - echo 'eval "`pactup env --use-on-cd`"' >>$CONF_FILE + { + echo '' + echo '# pactup' + echo 'PACTUP_PATH="'"$INSTALL_DIR"'"' + echo 'if [ -d "$PACTUP_PATH" ]; then' + echo ' export PATH="'$INSTALL_DIR':$PATH"' + echo ' eval "`pactup env --use-on-cd`"' + echo 'fi' + } | tee -a "$CONF_FILE" elif [ "$CURRENT_SHELL" = "fish" ]; then CONF_FILE=$HOME/.config/fish/conf.d/pactup.fish ensure_containing_dir_exists "$CONF_FILE" echo "Installing for Fish. Appending the following to $CONF_FILE:" - echo "" - echo ' # pactup' - echo ' set PATH "'"$INSTALL_DIR"'" $PATH' - echo ' pactup env --use-on-cd | source' - - echo '' >>$CONF_FILE - echo '# pactup' >>$CONF_FILE - echo 'set PATH "'"$INSTALL_DIR"'" $PATH' >>$CONF_FILE - echo 'pactup env --use-on-cd | source' >>$CONF_FILE + { + echo '' + echo '# pactup' + echo 'set PACTUP_PATH "'"$INSTALL_DIR"'"' + echo 'if [ -d "$PACTUP_PATH" ]' + echo ' set PATH "$PACTUP_PATH" $PATH' + echo ' pactup env --use-on-cd | source' + echo 'end' + } | tee -a "$CONF_FILE" elif [ "$CURRENT_SHELL" = "bash" ]; then if [ "$OS" = "Darwin" ]; then @@ -208,15 +208,15 @@ setup_shell() { fi ensure_containing_dir_exists "$CONF_FILE" echo "Installing for Bash. Appending the following to $CONF_FILE:" - echo "" - echo ' # pactup' - echo ' export PATH="'"$INSTALL_DIR"':$PATH"' - echo ' eval "`pactup env --use-on-cd`"' - - echo '' >>$CONF_FILE - echo '# pactup' >>$CONF_FILE - echo 'export PATH="'"$INSTALL_DIR"':$PATH"' >>$CONF_FILE - echo 'eval "`pactup env --use-on-cd`"' >>$CONF_FILE + { + echo '' + echo '# pactup' + echo 'PACTUP_PATH="'"$INSTALL_DIR"'"' + echo 'if [ -d "$PACTUP_PATH" ]; then' + echo ' export PATH="$PACTUP_PATH:$PATH"' + echo ' eval "`fnm env --use-on-cd`"' + echo 'fi' + } | tee -a "$CONF_FILE" else echo "Could not infer shell type. Please set up manually. $CURRENT_SHELL" diff --git a/src/commands/env.rs b/src/commands/env.rs index 813cd1b..967a25f 100644 --- a/src/commands/env.rs +++ b/src/commands/env.rs @@ -1,6 +1,5 @@ use super::command::Command; use crate::config::PactupConfig; -use crate::directories; use crate::fs::symlink_dir; use crate::outln; use crate::path_ext::PathExt; @@ -36,7 +35,7 @@ fn generate_symlink_path() -> String { } fn make_symlink(config: &PactupConfig) -> Result { - let base_dir = directories::multishell_storage().ensure_exists_silently(); + let base_dir = config.multishell_storage().ensure_exists_silently(); let mut temp_dir = base_dir.join(generate_symlink_path()); while temp_dir.exists() { diff --git a/src/commands/install.rs b/src/commands/install.rs index 6c73ac0..550a18b 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -154,16 +154,6 @@ impl Command for Install { Ok(()) => {} }; - if let UserVersion::Full(Version::Nightly(nightly_type)) = current_version { - let alias_name = nightly_type.to_string(); - debug!( - "Tagging {} as alias for {}", - alias_name.cyan(), - version.v_str().cyan() - ); - create_alias(config, &alias_name, version)?; - } - if !config.default_version_dir().exists() { debug!( "Tagging {} as the default version", @@ -172,9 +162,30 @@ impl Command for Install { create_alias(config, "default", &release.tag_name)?; } + if let Some(tagged_alias) = current_version.inferred_alias() { + tag_alias(config, version, &tagged_alias)?; + } + Ok(()) } } + +fn tag_alias( + config: &PactupConfig, + matched_version: &Version, + alias: &Version, +) -> Result<(), Error> { + let alias_name = alias.v_str(); + debug!( + "Tagging {} as alias for {}", + alias_name.cyan(), + matched_version.v_str().cyan() + ); + create_alias(config, &alias_name, matched_version)?; + + Ok(()) +} + #[derive(Debug, Error)] pub enum Error { #[error("Can't download the requested binary: {}", source)] diff --git a/src/commands/ls_remote.rs b/src/commands/ls_remote.rs index 85f45d1..5ab9528 100644 --- a/src/commands/ls_remote.rs +++ b/src/commands/ls_remote.rs @@ -53,10 +53,9 @@ impl super::command::Command for LsRemote { } if self.latest { - all_versions.truncate(1); + all_versions.drain(0..all_versions.len() - 1); } - all_versions.sort_by_key(|v| v.tag_name.clone()); if let SortingMethod::Descending = self.sort { all_versions.reverse(); } diff --git a/src/config.rs b/src/config.rs index 14eeb7b..6bb6ef7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,7 @@ -use crate::arch::Arch; use crate::log_level::LogLevel; use crate::path_ext::PathExt; use crate::version_file_strategy::VersionFileStrategy; -use dirs::{data_dir, home_dir}; +use crate::{arch::Arch, directories::Directories}; #[derive(clap::Parser, Debug)] pub struct PactupConfig { @@ -28,7 +27,7 @@ pub struct PactupConfig { /// The root directory of pact installations. #[clap( - long = "pact-dir", + long = "pactup-dir", env = "PACTUP_PACT_DIR", global = true, hide_env_values = true @@ -78,6 +77,9 @@ pub struct PactupConfig { hide_env_values = true )] version_file_strategy: VersionFileStrategy, + + #[clap(skip)] + directories: Directories, } impl Default for PactupConfig { @@ -90,6 +92,7 @@ impl Default for PactupConfig { log_level: LogLevel::Info, arch: Arch::default(), version_file_strategy: VersionFileStrategy::default(), + directories: Directories::default(), } } } @@ -116,19 +119,7 @@ impl PactupConfig { return dir; } - let legacy = home_dir() - .map(|dir| dir.join(".pactup")) - .filter(|dir| dir.exists()); - - let modern = data_dir().map(|dir| dir.join("pactup")); - - if let Some(dir) = legacy { - return dir; - } - - modern - .expect("Can't get data directory") - .ensure_exists_silently() + self.directories.default_base_dir() } pub fn installations_dir(&self) -> std::path::PathBuf { @@ -138,6 +129,10 @@ impl PactupConfig { .ensure_exists_silently() } + pub fn multishell_storage(&self) -> std::path::PathBuf { + self.directories.multishell_storage() + } + pub fn default_version_dir(&self) -> std::path::PathBuf { self.aliases_dir().join("default") } diff --git a/src/directories.rs b/src/directories.rs index 88e26cd..d7e93ca 100644 --- a/src/directories.rs +++ b/src/directories.rs @@ -1,26 +1,78 @@ +use etcetera::BaseStrategy; use std::path::PathBuf; +use crate::path_ext::PathExt; + fn xdg_dir(env: &str) -> Option { - let env_var = std::env::var(env).ok()?; - Some(PathBuf::from(env_var)) + if cfg!(windows) { + let env_var = std::env::var(env).ok()?; + Some(PathBuf::from(env_var)) + } else { + // On non-Windows platforms, `etcetera` already handles XDG variables + None + } } -fn state_dir() -> Option { - xdg_dir("XDG_STATE_HOME").or_else(dirs::state_dir) +fn runtime_dir(basedirs: &impl BaseStrategy) -> Option { + xdg_dir("XDG_RUNTIME_DIR").or_else(|| basedirs.runtime_dir()) } -fn cache_dir() -> Option { - xdg_dir("XDG_CACHE_HOME").or_else(dirs::cache_dir) +fn state_dir(basedirs: &impl BaseStrategy) -> Option { + xdg_dir("XDG_STATE_HOME").or_else(|| basedirs.state_dir()) } -fn runtime_dir() -> Option { - xdg_dir("XDG_RUNTIME_DIR").or_else(dirs::runtime_dir) +fn cache_dir(basedirs: &impl BaseStrategy) -> PathBuf { + xdg_dir("XDG_CACHE_HOME").unwrap_or_else(|| basedirs.cache_dir()) } -pub fn multishell_storage() -> PathBuf { - runtime_dir() - .or_else(state_dir) - .or_else(cache_dir) - .unwrap_or_else(std::env::temp_dir) - .join("pactup_multishells") +/// A helper struct for directories in fnm that uses XDG Base Directory Specification +/// if applicable for the platform. +#[derive(Debug)] +pub struct Directories( + #[cfg(windows)] etcetera::base_strategy::Windows, + #[cfg(not(windows))] etcetera::base_strategy::Xdg, +); + +impl Default for Directories { + fn default() -> Self { + Self(etcetera::choose_base_strategy().expect("choosing base strategy")) + } +} + +impl Directories { + pub fn strategy(&self) -> &impl BaseStrategy { + &self.0 + } + + pub fn default_base_dir(&self) -> PathBuf { + let strategy = self.strategy(); + let modern = strategy.data_dir().join("pactup"); + if modern.exists() { + return modern; + } + + let legacy = strategy.home_dir().join(".pactup"); + if legacy.exists() { + return legacy; + } + + #[cfg(target_os = "macos")] + { + let basedirs = etcetera::base_strategy::Apple::new().expect("Can't get home directory"); + let legacy = basedirs.data_dir().join("pactup"); + if legacy.exists() { + return legacy; + } + } + + modern.ensure_exists_silently() + } + + pub fn multishell_storage(&self) -> PathBuf { + let basedirs = self.strategy(); + let dir = runtime_dir(basedirs) + .or_else(|| state_dir(basedirs)) + .unwrap_or_else(|| cache_dir(basedirs)); + dir.join("pactup_multishells") + } } diff --git a/src/shell/bash.rs b/src/shell/bash.rs index c7e270d..f99d325 100644 --- a/src/shell/bash.rs +++ b/src/shell/bash.rs @@ -18,7 +18,7 @@ impl Shell for Bash { .ok_or_else(|| anyhow::anyhow!("Can't convert path to string"))?; let path = super::windows_compat::maybe_fix_windows_path(path).unwrap_or_else(|| path.to_string()); - Ok(format!("export PATH={path:?}:$PATH")) + Ok(format!("export PATH={path:?}:\"$PATH\"")) } fn set_env_var(&self, name: &str, value: &str) -> String { diff --git a/src/shell/infer/windows.rs b/src/shell/infer/windows.rs index bc2c207..10cc8ab 100644 --- a/src/shell/infer/windows.rs +++ b/src/shell/infer/windows.rs @@ -14,8 +14,8 @@ pub fn infer_shell() -> Option> { current_pid = process.parent(); let process_name = process .exe() - .file_stem() - .and_then(OsStr::to_str) + .and_then(|x| x.file_stem()) + .and_then(|x| x.to_str()) .map(str::to_lowercase); if let Some(shell) = process_name .as_ref() diff --git a/src/user_version.rs b/src/user_version.rs index 622f0e0..a030628 100644 --- a/src/user_version.rs +++ b/src/user_version.rs @@ -63,6 +63,17 @@ impl UserVersion { } } } + + /// The inferred alias for the user version, if it exists. + pub fn inferred_alias(&self) -> Option { + match self { + UserVersion::Full(Version::Latest) => Some(Version::Latest), + UserVersion::Full(Version::Nightly(nightly_type)) => { + Some(Version::Nightly(nightly_type.clone())) + } + _ => None, + } + } } fn next_of<'a, T: FromStr, It: Iterator>(i: &mut It) -> Option {