utpm 0.3.0

UTPM is a package manager for local and remote Typst packages. Quickly create and manage projects and templates on your system, and publish them directly to Typst Universe.
Documentation
use std::{
    env::{self, current_dir},
    fs::read_dir,
    path::{Path, PathBuf},
};

use crate::path;

use super::state::{Result, UtpmError};

/// The URL for the official typst packages repository.
pub const TYPST_PACKAGE_URL: &str = "https://github.com/typst/packages";
/// The subdirectory for UTPM's own data files.
pub const UTPM_SUBDIR: &str = "utpm";
/// The name of the manifest file.
pub const MANIFEST_FILE: &str = "typst.toml";
/// The subdirectory for locally cloned git packages.
pub const LOCAL_PACKAGES: &str = "git-packages";

fn env_path(key: &str) -> Option<PathBuf> {
    env::var(key).ok().map(PathBuf::from)
}

fn not_found(message: &str) -> UtpmError {
    std::io::Error::new(std::io::ErrorKind::NotFound, message).into()
}

/// Gets the path to the directory for downloaded packages from the typst registry.
///
/// This path can be overridden by setting the `TYPST_PACKAGE_CACHE_PATH` environment variable.
/// It is used for storing packages downloaded from the typst registry.
pub fn package_cache_path() -> Result<PathBuf> {
    env_path("TYPST_PACKAGE_CACHE_PATH")
        .or_else(typst_kit::package::default_package_cache_path)
        .ok_or_else(|| not_found("Could not find package cache directory"))
}

/// Gets the path to the directory for local packages.
///
/// This path can be overridden by setting the `TYPST_PACKAGE_PATH` environment variable.
/// It is used for storing local packages.
pub fn package_path() -> Result<PathBuf> {
    env_path("TYPST_PACKAGE_PATH")
        .or_else(typst_kit::package::default_package_path)
        .ok_or_else(|| not_found("Could not find package directory"))
}

/// Gets the path to UTPM's data directory.
///
/// Used for storing temporary files.
///
/// This path can be overridden by setting the `UTPM_DATA_PATH` environment variable.
/// It is used for storing local packages.
pub fn utpm_data_path() -> Result<PathBuf> {
    env_path("UTPM_DATA_PATH")
        .or_else(|| dirs::data_dir().map(|data_dir| path!(data_dir, UTPM_SUBDIR)))
        .ok_or_else(|| not_found("Could not find utpm data directory"))
}

/// Gets the path to the default directory for cloned git packages.
pub fn local_package_path() -> Result<PathBuf> {
    Ok(path!(utpm_data_path()?, LOCAL_PACKAGES))
}

/// Gets the current working directory.
///
/// This path can be overridden by setting the `UTPM_CURRENT_DIR` environment variable.
/// It is used for reading and writing the `typst.toml` manifest.
pub fn get_current_dir() -> Result<PathBuf> {
    env_path("UTPM_CURRENT_DIR")
        .ok_or(())
        .or_else(|()| current_dir())
        .map_err(Into::into)
}

/// Checks if a directory at the given path is not empty.
pub fn has_content(path: impl AsRef<Path>) -> Result<bool> {
    Ok(read_dir(path)?.next().is_some())
}

/// Checks if a directory exists at the given path.
pub fn check_path_dir(path: impl AsRef<Path>) -> bool {
    path.as_ref().is_dir()
}

/// Checks if a file exists at the given path.
pub fn check_path_file(path: impl AsRef<Path>) -> bool {
    path.as_ref().is_file()
}