Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,5 @@ tasks:
echo "$new_version" > VERSION;
echo "bumped version: $current -> $new_version";



upgrade:
- cargo upgrade
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.5
0.4.6
15 changes: 14 additions & 1 deletion packages/corelib/src/epkg/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub fn install_git_commit(
package: &str,
git: &str,
rev: &str,
root: Option<&str>,
bar: Option<&Arc<cu::ProgressBar>>,
) -> cu::Result<()> {
let mut state = cargo::instance()?;
Expand All @@ -93,6 +94,10 @@ pub fn install_git_commit(
// rust-toolchain file, which will override the rust toolchain being used
.current_dir(hmgr::paths::home())
.args(["install", package, "--git", git, "--rev", rev, "--locked"]);
let command = match root {
None => command,
Some(root) => command.args(["--force", "-q", "--root", root]),
};
let command = add_platform_build_args(command);
let (child, bar) = command
.preset(
Expand All @@ -109,12 +114,20 @@ pub fn install_git_commit(

/// Install a package using `cargo install`
#[cu::context("failed to install '{package}' with cargo")]
pub fn install(package: &str, bar: Option<&Arc<cu::ProgressBar>>) -> cu::Result<()> {
pub fn install(
package: &str,
root: Option<&str>,
bar: Option<&Arc<cu::ProgressBar>>,
) -> cu::Result<()> {
let mut state = cargo::instance()?;
let command = cu::which("cargo")?
.command()
.current_dir(hmgr::paths::home())
.args(["install", package, "--locked"]);
let command = match root {
None => command,
Some(root) => command.args(["-q", "--root", root]),
};
let command = add_platform_build_args(command);
let (child, bar) = command
.preset(
Expand Down
1 change: 1 addition & 0 deletions packages/corelib/src/hmgr/env/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ impl Env {
Item::Bash(_) => self.bash_dirty = true,
Item::Zsh(_) => self.zsh_dirty = true,
Item::LinkBin(_, _, _) => {}
Item::LinkSysBin(_, _) => {}
Item::ShimBin(_, _) => {}
Item::Pwsh(_) => {}
Item::Cmd(_) => {}
Expand Down
1 change: 1 addition & 0 deletions packages/corelib/src/hmgr/env/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl Env {
Item::Pwsh(_) => self.pwsh_dirty = true,
Item::Cmd(_) => self.cmd_dirty = true,
Item::LinkBin(_, _, _) => {}
Item::LinkSysBin(_, _) => {}
Item::ShimBin(_, _) => {}
Item::Bash(_) => {}
Item::Zsh(_) => {}
Expand Down
2 changes: 1 addition & 1 deletion packages/corelib/src/hmgr/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod windows {
use std::collections::BTreeMap;
use std::sync::Mutex;

pub use win_envedit::get_user;
pub use win_envedit::{get_system, get_user};
static USER_THIS_SESSION: Mutex<BTreeMap<String, String>> = Mutex::new(BTreeMap::new());
/// Get user environment variable at the start of the session,
/// before any set calls
Expand Down
71 changes: 54 additions & 17 deletions packages/corelib/src/hmgr/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl ItemMgr {
#[cfg(target_os = "linux")]
Item::SessionEnvVar(_, _, _) => {}
Item::LinkBin(_, _, _) => self.link_dirty = true,
Item::LinkSysBin(_, _) => self.link_dirty = true,
Item::ShimBin(_, _) => self.shim_dirty = true,
Item::Pwsh(_) => {}
Item::Bash(_) => {}
Expand All @@ -94,6 +95,7 @@ impl ItemMgr {
package: Option<&str>, // none for removing all
) -> cu::Result<()> {
let mut bin_to_remove = vec![];
let mut sbin_to_remove = vec![];
#[cfg(windows)]
let mut env_to_remove = BTreeMap::new();
#[cfg(windows)]
Expand Down Expand Up @@ -128,6 +130,10 @@ impl ItemMgr {
bin_to_remove.push(bin.to_string());
// removing a link does not make links dirty
}
Item::LinkSysBin(bin, _) => {
sbin_to_remove.push(bin.to_string());
// removing a link does not make links dirty
}
Item::ShimBin(bin, _) => {
bin_to_remove.push(bin.to_string());
self.shim_dirty = true;
Expand All @@ -150,6 +156,14 @@ impl ItemMgr {
}
}
}
if !sbin_to_remove.is_empty() {
let bin_root = hmgr::paths::sbin_root();
for bin in sbin_to_remove {
if let Err(e) = opfs::safe_remove_link(&bin_root.join(bin)) {
cu::warn!("failed to remove old link: {e}");
}
}
}

#[cfg(windows)]
{
Expand Down Expand Up @@ -215,25 +229,40 @@ impl ItemMgr {
#[cu::context("failed to build binary links")]
fn rebuild_links(&mut self) -> cu::Result<()> {
let bin_root = hmgr::paths::bin_root();
let sbin_root = hmgr::paths::sbin_root();
cu::fs::make_dir(&bin_root)?;
cu::fs::make_dir(&sbin_root)?;
let mut link_paths = vec![];
let mut sys_link_paths = vec![];
for entry in &self.items {
let Item::LinkBin(from, to, non_exe) = &entry.item else {
continue;
};
let link_path = bin_root.join(from);
if link_path.exists() {
// assume existing file is from linking previously
continue;
match &entry.item {
Item::LinkBin(from, to, non_exe) => {
let link_path = bin_root.join(from);
if link_path.exists() {
// assume existing file is from linking previously
continue;
}
link_paths.push((link_path, to, non_exe));
}
Item::LinkSysBin(from, to) => {
let link_path = sbin_root.join(from);
if link_path.exists() {
// assume existing file is from linking previously
continue;
}
sys_link_paths.push((link_path, to));
}
_ => {}
}
link_paths.push((link_path, to, non_exe));
}
let link_paths2: Vec<(&Path, &Path)> = link_paths
let link_paths_iter = link_paths
.iter()
.map(|(x, y, _)| (x.as_path(), y.as_ref()))
.collect();

opfs::hardlink_files(&link_paths2)?;
.map(|(x, y, _)| (x.as_path(), Path::new(y)));
opfs::hardlink_files(link_paths_iter)?;
let sys_link_paths_iter = sys_link_paths
.iter()
.map(|(x, y)| (x.as_path(), Path::new(y)));
opfs::hardlink_files(sys_link_paths_iter)?;

#[cfg(not(windows))]
{
Expand Down Expand Up @@ -315,7 +344,7 @@ impl ItemMgr {
let shim_binary_old = hmgr::paths::shim_binary_old();
if shim_binary.exists() {
// hardlink the old binary, so we can start deleting the old links
opfs::hardlink_files(&[(&shim_binary_old, &shim_binary)])?;
opfs::hardlink_files([(&shim_binary_old, &shim_binary)].into_iter())?;
}

// the old binary could be in use, which will not allow us to copy it,
Expand All @@ -333,10 +362,9 @@ impl ItemMgr {
}
let link_paths = link_paths
.iter()
.map(|x| (x.as_path(), shim_binary.as_path()))
.collect::<Vec<_>>();
.map(|x| (x.as_path(), shim_binary.as_path()));
cu::check!(
opfs::hardlink_files(&link_paths),
opfs::hardlink_files(link_paths),
"failed to create hardlinks for shim binaries"
)?;

Expand Down Expand Up @@ -382,6 +410,10 @@ pub enum Item {
/// in the install directory.
LinkBin(String, String, bool /* non_executable */),

/// Link a system binary (in the HOME/sbin directory) to a location
/// in the install directory.
LinkSysBin(String, String),

/// Create a shim binary that invokes a command.
///
/// This is useful in 2 scenarios:
Expand Down Expand Up @@ -436,6 +468,11 @@ impl Item {
Self::LinkBin(name.into(), target.into(), false)
}

#[inline(always)]
pub fn link_sys_bin(name: impl Into<String>, target: impl Into<String>) -> Self {
Self::LinkSysBin(name.into(), target.into())
}

#[inline(always)]
#[cfg(not(windows))]
pub fn link_non_exe(name: impl Into<String>, target: impl Into<String>) -> Self {
Expand Down
2 changes: 2 additions & 0 deletions packages/corelib/src/hmgr/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub(crate) fn home() -> &'static Path {
home! {
bin_root: "bin",
binary: bin_root / file,
sbin_root: "sbin",
system_binary: sbin_root / file,
config_root: "config",
config_toml: config_root / "core.toml",
install_root: "install",
Expand Down
16 changes: 14 additions & 2 deletions packages/corelib/src/opfs/fs_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,25 @@ pub fn symlink_files(paths: &[(&Path, &Path)]) -> cu::Result<()> {
/// Create hardlinks. `from` is where the link will be and `to` is the target of the link
#[cfg(windows)]
#[cu::context("failed to create hard links")]
pub fn hardlink_files(paths: &[(&Path, &Path)]) -> cu::Result<()> {
pub fn hardlink_files(
paths: impl Iterator<Item = (impl AsRef<Path>, impl AsRef<Path>)>,
) -> cu::Result<()> {
let mut script = String::new();
let mut empty = true;
for (from, to) in paths {
empty = false;
let from = from.as_ref();
let to = to.as_ref();
safe_remove_link(from)?;
let from_abs = from.normalize()?;
let to_abs = to.normalize()?;
let from_str = from_abs.as_utf8()?;
let to_str = to_abs.as_utf8()?;
build_link_powershell(&mut script, "HardLink", from_str, to_str);
}
if empty {
return Ok(());
}
cu::which("powershell")?
.command()
.args(["-NoLogo", "-NoProfile", "-c", &script])
Expand All @@ -90,8 +99,11 @@ fn build_link_powershell(out: &mut String, link_type: &str, from: &str, to: &str
/// Create hardlinks. `from` is where the link will be and `to` is the target of the link
#[cfg(not(windows))]
#[cu::context("failed to create hard links")]
pub fn hardlink_files(paths: &[(&Path, &Path)]) -> cu::Result<()> {
pub fn hardlink_files(
paths: impl Iterator<Item = (impl AsRef<Path>, impl AsRef<Path>)>,
) -> cu::Result<()> {
for (from, to) in paths {
let from = from.as_ref();
cu::fs::remove(from)?;
std::fs::hard_link(to, from)?;
}
Expand Down
11 changes: 7 additions & 4 deletions packages/registry/metadata.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@ SHA.'opfs::CpuArch::X64' = "9965153b4d3308dd5b3cb3d1a800b89b7b93a345b09f208e0f9b
VERSION = "1.19.1"

[coreutils]
ALIAS_VERSION = "13"
ALIAS_VERSION = "14"
eza.VERSION = "0.23.4"
uutils.VERSION = "0.9.0"
zip.VERSION = "3.0"
unzip.VERSION = "6.0"
tar.VERSION = "1.35"
which.VERSION = "2.25"
bash.VERSION = "5.3.9"
bash.VERSION = "5.3.12"
bash_cmp.VERSION = "2.17.0"
yay.VERSION = "12.5.7"
yay.VERSION = "12.6.0"
ms_coreutils.VERSION = "2026.5.29"
ms_coreutils.REPO = "https://github.com/microsoft/coreutils"
ms_coreutils.COMMIT = "e0dea0bffc58dd697f3ae60315f8579e2bf9b86f" # -- MUST BE MANUALLY PICKED! -- new utils/breaking changes likely to the setup process
uutils_sed.VERSION = "0.1.1"

[shellutils]
ALIAS_VERSION = "8"
Expand Down
2 changes: 1 addition & 1 deletion packages/registry/src/packages/cargo-binstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn install(ctx: &Context) -> cu::Result<()> {
if cu::which("cargo-binstall").is_ok() {
epkg::cargo::binstall("cargo-binstall", ctx.bar_ref())
} else {
epkg::cargo::install("cargo-binstall", ctx.bar_ref())
epkg::cargo::install("cargo-binstall", None, ctx.bar_ref())
}
}

Expand Down
31 changes: 4 additions & 27 deletions packages/registry/src/packages/coreutils/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,11 @@ key = ["windows"]
comment = "Options for Windows-specific settings"
children = [
{
key = ["exclude-coreutils"],
value = [],
key = ["prefer-gnu"],
value = true,
comment = """
Exclude creating shim executables for coreutils listed.
You would have to run coreutils <util> to run the util.
Set it to the following to avoid conflicts with CMD and
native Windows utilities with the same names:
exclude-coreutils = [
# System32
'expand',
'hostname',
'more',
'whoami',
'sort',
'find',
# CMD
'rmdir',
'dir',
'type',
]

'diff' and 'find' can also be excluded (despite not being actually coreutils)

The following utils are usually not used, and often conflicts,
so they are always removed:
- `link.exe` - conflicts with MSVC

For commands with compatibility for both DOS and GNU,
prefer GNU when ambiguous
"""
},
{
Expand All @@ -38,7 +16,6 @@ so they are always removed:
comment = """
Add a doskey macro to make the mkdir command in CMD GNU-compatible.
(Essentially alias mkdir in CMD to mkdir -p)
This will work even if mkdir is excluded in exclude-coreutils
"""
}
]
38 changes: 19 additions & 19 deletions packages/registry/src/packages/coreutils/eza.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
use crate::pre::*;

pub fn verify() -> cu::Result<Verified> {
let v = check_cargo!("eza");
check_outdated!(&v.version, metadata[coreutils::eza]::VERSION);
check_in_shaft!("eza");
let version = get_version()?;
check_outdated!(&version, metadata[coreutils::eza]::VERSION);
Ok(Verified::UpToDate)
}

fn get_version() -> cu::Result<String> {
let output = command_output!("eza", ["--version"]);
let output = cu::check!(
output.lines().find(|l| l.starts_with("v")),
"failed to parse eza --version output: failed to find version line"
)?;
let version = output.strip_prefix('v').unwrap_or(output);
let version = version.split_once(' ').map(|a| a.0).unwrap_or(version);
Ok(version.trim().to_string())
}

pub fn install(ctx: &Context) -> cu::Result<()> {
if let Ok(Verified::UpToDate) = verify() {
return Ok(());
}
epkg::cargo::install("eza", ctx.bar_ref())
}

pub fn uninstall() -> cu::Result<()> {
let eza_path = hmgr::paths::binary(bin_name!("eza"));
cu::fs::remove(&eza_path)?;
epkg::cargo::uninstall("eza")
let install_dir = cu::path!((ctx.install_dir()) / "eza").into_utf8()?;
epkg::cargo::install("eza", Some(&install_dir), ctx.bar_ref())
}

pub fn configure(ctx: &Context) -> cu::Result<()> {
// Delete existing eza binary to find the original
let eza_path = hmgr::paths::binary(bin_name!("eza"));
cu::fs::remove(&eza_path)?;
let eza_src = cu::which("eza")?;
cu::fs::copy(&eza_src, &eza_path)?;

ctx.add_item(Item::shim_bin(
bin_name!("ls"),
ShimCommand::target(eza_path.into_utf8()?),
))?;
let bin = cu::path!((ctx.install_dir()) / "eza" / "bin" / bin_name!("eza")).into_utf8()?;
ctx.add_item(Item::link_bin(bin_name!("ls"), bin.clone()))?;
ctx.add_item(Item::link_bin(bin_name!("eza"), bin))?;
Ok(())
}
Loading
Loading