feat: add PESDE_ROOT for bin packages

This commit is contained in:
daimond113 2024-09-03 23:08:08 +02:00
parent 71eacb8673
commit d321b8b0aa
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
10 changed files with 188 additions and 151 deletions

View file

@ -1,11 +1,8 @@
use std::{ffi::OsString, process::Command}; use crate::cli::{config::read_config, VersionedPackageName};
use anyhow::Context; use anyhow::Context;
use clap::Args; use clap::Args;
use semver::VersionReq;
use crate::cli::{config::read_config, VersionedPackageName};
use pesde::{ use pesde::{
linking::generator::generate_bin_linking_module,
manifest::target::TargetKind, manifest::target::TargetKind,
names::PackageName, names::PackageName,
source::{ source::{
@ -14,6 +11,8 @@ use pesde::{
}, },
Project, Project,
}; };
use semver::VersionReq;
use std::{env::current_dir, ffi::OsString, io::Write, process::Command};
#[derive(Debug, Args)] #[derive(Debug, Args)]
pub struct ExecuteCommand { pub struct ExecuteCommand {
@ -72,15 +71,28 @@ impl ExecuteCommand {
fs.write_to(tempdir.path(), project.cas_dir(), true) fs.write_to(tempdir.path(), project.cas_dir(), true)
.context("failed to write package contents")?; .context("failed to write package contents")?;
let mut caller =
tempfile::NamedTempFile::new_in(tempdir.path()).context("failed to create tempfile")?;
caller
.write_all(
generate_bin_linking_module(
tempdir.path(),
&format!("{:?}", bin_path.to_path(tempdir.path())),
)
.as_bytes(),
)
.context("failed to write to tempfile")?;
let status = Command::new("lune") let status = Command::new("lune")
.arg("run") .arg("run")
.arg(bin_path.to_path(tempdir.path())) .arg(caller.path())
.arg("--") .arg("--")
.args(&self.args) .args(&self.args)
.current_dir(project.package_dir()) .current_dir(current_dir().context("failed to get current directory")?)
.status() .status()
.context("failed to run script")?; .context("failed to run script")?;
drop(caller);
drop(tempdir); drop(tempdir);
std::process::exit(status.code().unwrap_or(1)) std::process::exit(status.code().unwrap_or(1))

View file

@ -9,22 +9,17 @@ use pesde::{
errors::ManifestReadError, names::PackageName, scripts::ScriptName, Project, DEFAULT_INDEX_NAME, errors::ManifestReadError, names::PackageName, scripts::ScriptName, Project, DEFAULT_INDEX_NAME,
}; };
use crate::cli::config::read_config; use crate::cli::{config::read_config, HOME_DIR};
#[derive(Debug, Args)] #[derive(Debug, Args)]
pub struct InitCommand {} pub struct InitCommand {}
fn script_contents(path: &Path) -> String { fn script_contents(path: &Path) -> String {
format!( format!(
concat!(
r#"local process = require("@lune/process") r#"local process = require("@lune/process")
local home_dir = if process.os == "windows" then process.env.userprofile else process.env.HOME local home_dir = if process.os == "windows" then process.env.userprofile else process.env.HOME
require(home_dir .. ""#, require(home_dir .. "/{HOME_DIR}/scripts/{}"#,
"/.",
env!("CARGO_PKG_NAME"),
r#"/scripts/{}")"#,
),
path.display() path.display()
) )
} }

View file

@ -43,7 +43,6 @@ fn bin_link_file(alias: &str) -> String {
let prefix = String::new(); let prefix = String::new();
#[cfg(unix)] #[cfg(unix)]
let prefix = "#!/usr/bin/env -S lune run\n"; let prefix = "#!/usr/bin/env -S lune run\n";
// TODO: reimplement workspace support in this
format!( format!(
r#"{prefix}local process = require("@lune/process") r#"{prefix}local process = require("@lune/process")
local fs = require("@lune/fs") local fs = require("@lune/fs")

View file

@ -1,15 +1,14 @@
use std::{ffi::OsString, path::PathBuf, process::Command}; use crate::cli::up_to_date_lockfile;
use anyhow::Context; use anyhow::Context;
use clap::Args; use clap::Args;
use relative_path::RelativePathBuf;
use crate::cli::up_to_date_lockfile;
use pesde::{ use pesde::{
linking::generator::generate_bin_linking_module,
names::{PackageName, PackageNames}, names::{PackageName, PackageNames},
source::traits::PackageRef, source::traits::PackageRef,
Project, PACKAGES_CONTAINER_NAME, Project, PACKAGES_CONTAINER_NAME,
}; };
use relative_path::RelativePathBuf;
use std::{env::current_dir, ffi::OsString, io::Write, path::PathBuf, process::Command};
#[derive(Debug, Args)] #[derive(Debug, Args)]
pub struct RunCommand { pub struct RunCommand {
@ -25,15 +24,28 @@ pub struct RunCommand {
impl RunCommand { impl RunCommand {
pub fn run(self, project: Project) -> anyhow::Result<()> { pub fn run(self, project: Project) -> anyhow::Result<()> {
let run = |path: PathBuf| { let run = |path: PathBuf| {
let mut caller = tempfile::NamedTempFile::new().expect("failed to create tempfile");
caller
.write_all(
generate_bin_linking_module(
project.package_dir(),
&format!("{:?}", path.to_string_lossy()),
)
.as_bytes(),
)
.expect("failed to write to tempfile");
let status = Command::new("lune") let status = Command::new("lune")
.arg("run") .arg("run")
.arg(path) .arg(caller.path())
.arg("--") .arg("--")
.args(&self.args) .args(&self.args)
.current_dir(project.package_dir()) .current_dir(current_dir().expect("failed to get current directory"))
.status() .status()
.expect("failed to run script"); .expect("failed to run script");
drop(caller);
std::process::exit(status.code().unwrap_or(1)) std::process::exit(status.code().unwrap_or(1))
}; };

View file

@ -18,7 +18,7 @@ pub mod auth;
pub mod commands; pub mod commands;
pub mod config; pub mod config;
pub mod files; pub mod files;
pub mod scripts; pub mod repos;
pub mod version; pub mod version;
pub const HOME_DIR: &str = concat!(".", env!("CARGO_PKG_NAME")); pub const HOME_DIR: &str = concat!(".", env!("CARGO_PKG_NAME"));

114
src/cli/repos.rs Normal file
View file

@ -0,0 +1,114 @@
use crate::{
cli::{config::read_config, home_dir},
util::authenticate_conn,
};
use anyhow::Context;
use gix::remote::Direction;
use pesde::Project;
use std::path::Path;
fn update_repo<P: AsRef<Path>>(
name: &str,
path: P,
url: gix::Url,
project: &Project,
) -> anyhow::Result<()> {
let path = path.as_ref();
if path.exists() {
let repo = gix::open(path).context(format!("failed to open {name} repository"))?;
let remote = repo
.find_default_remote(Direction::Fetch)
.context(format!("missing default remote of {name} repository"))?
.context(format!(
"failed to find default remote of {name} repository"
))?;
let mut connection = remote.connect(Direction::Fetch).context(format!(
"failed to connect to default remote of {name} repository"
))?;
authenticate_conn(&mut connection, project.auth_config());
let results = connection
.prepare_fetch(gix::progress::Discard, Default::default())
.context(format!("failed to prepare {name} repository fetch"))?
.receive(gix::progress::Discard, &false.into())
.context(format!("failed to receive new {name} repository contents"))?;
let remote_ref = results
.ref_map
.remote_refs
.first()
.context(format!("failed to get remote refs of {name} repository"))?;
let unpacked = remote_ref.unpack();
let oid = unpacked
.1
.or(unpacked.2)
.context("couldn't find oid in remote ref")?;
let tree = repo
.find_object(oid)
.context(format!("failed to find {name} repository tree"))?
.peel_to_tree()
.context(format!("failed to peel {name} repository object to tree"))?;
let mut index = gix::index::File::from_state(
gix::index::State::from_tree(&tree.id, &repo.objects, Default::default()).context(
format!("failed to create index state from {name} repository tree"),
)?,
repo.index_path(),
);
let opts = gix::worktree::state::checkout::Options {
overwrite_existing: true,
destination_is_initially_empty: false,
..Default::default()
};
gix::worktree::state::checkout(
&mut index,
repo.work_dir().context(format!("{name} repo is bare"))?,
repo.objects
.clone()
.into_arc()
.context("failed to clone objects")?,
&gix::progress::Discard,
&gix::progress::Discard,
&false.into(),
opts,
)
.context(format!("failed to checkout {name} repository"))?;
index
.write(gix::index::write::Options::default())
.context("failed to write index")?;
} else {
std::fs::create_dir_all(path).context(format!("failed to create {name} directory"))?;
gix::prepare_clone(url, path)
.context(format!("failed to prepare {name} repository clone"))?
.fetch_then_checkout(gix::progress::Discard, &false.into())
.context(format!("failed to fetch and checkout {name} repository"))?
.0
.main_worktree(gix::progress::Discard, &false.into())
.context(format!("failed to set {name} repository as main worktree"))?;
};
Ok(())
}
pub fn update_repo_dependencies(project: &Project) -> anyhow::Result<()> {
let home_dir = home_dir()?;
let config = read_config()?;
update_repo(
"scripts",
home_dir.join("scripts"),
config.scripts_repo,
project,
)?;
Ok(())
}

View file

@ -1,94 +0,0 @@
use crate::{
cli::{config::read_config, home_dir},
util::authenticate_conn,
};
use anyhow::Context;
use gix::remote::Direction;
use pesde::Project;
pub fn update_scripts_folder(project: &Project) -> anyhow::Result<()> {
let scripts_dir = home_dir()?.join("scripts");
if scripts_dir.exists() {
let repo = gix::open(&scripts_dir).context("failed to open scripts repository")?;
let remote = repo
.find_default_remote(Direction::Fetch)
.context("missing default remote of scripts repository")?
.context("failed to find default remote of scripts repository")?;
let mut connection = remote
.connect(Direction::Fetch)
.context("failed to connect to default remote of scripts repository")?;
authenticate_conn(&mut connection, project.auth_config());
let results = connection
.prepare_fetch(gix::progress::Discard, Default::default())
.context("failed to prepare scripts repository fetch")?
.receive(gix::progress::Discard, &false.into())
.context("failed to receive new scripts repository contents")?;
let remote_ref = results
.ref_map
.remote_refs
.first()
.context("failed to get remote refs of scripts repository")?;
let unpacked = remote_ref.unpack();
let oid = unpacked
.1
.or(unpacked.2)
.context("couldn't find oid in remote ref")?;
let tree = repo
.find_object(oid)
.context("failed to find scripts repository tree")?
.peel_to_tree()
.context("failed to peel scripts repository object to tree")?;
let mut index = gix::index::File::from_state(
gix::index::State::from_tree(&tree.id, &repo.objects, Default::default())
.context("failed to create index state from scripts repository tree")?,
repo.index_path(),
);
let opts = gix::worktree::state::checkout::Options {
overwrite_existing: true,
destination_is_initially_empty: false,
..Default::default()
};
gix::worktree::state::checkout(
&mut index,
repo.work_dir().context("scripts repo is bare")?,
repo.objects
.clone()
.into_arc()
.context("failed to clone objects")?,
&gix::progress::Discard,
&gix::progress::Discard,
&false.into(),
opts,
)
.context("failed to checkout scripts repository")?;
index
.write(gix::index::write::Options::default())
.context("failed to write index")?;
} else {
std::fs::create_dir_all(&scripts_dir).context("failed to create scripts directory")?;
let cli_config = read_config()?;
gix::prepare_clone(cli_config.scripts_repo, &scripts_dir)
.context("failed to prepare scripts repository clone")?
.fetch_then_checkout(gix::progress::Discard, &false.into())
.context("failed to fetch and checkout scripts repository")?
.0
.main_worktree(gix::progress::Discard, &false.into())
.context("failed to set scripts repository as main worktree")?;
};
Ok(())
}

View file

@ -125,8 +125,12 @@ pub fn get_lib_require_path(
} }
/// Generate a linking module for a binary /// Generate a linking module for a binary
pub fn generate_bin_linking_module(path: &str) -> String { pub fn generate_bin_linking_module<P: AsRef<Path>>(package_root: P, require_path: &str) -> String {
format!("return require({path})") format!(
r#"_G.PESDE_ROOT = {:?}
return require({require_path})"#,
package_root.as_ref().to_string_lossy()
)
} }
/// Get the require path for a binary /// Get the require path for a binary

View file

@ -139,14 +139,15 @@ impl Project {
version_id.version(), version_id.version(),
); );
if let Some((alias, types)) = package_types if let Some((alias, _)) = &node.node.direct.as_ref() {
if let Some((lib_file, types)) =
node.target.lib_path().and_then(|lib_file| {
package_types
.get(name) .get(name)
.and_then(|v| v.get(version_id)) .and_then(|v| v.get(version_id))
.and_then(|types| { .map(|types| (lib_file, types))
node.node.direct.as_ref().map(|(alias, _)| (alias, types))
}) })
{ {
if let Some(lib_file) = node.target.lib_path() {
write_cas( write_cas(
base_folder.join(format!("{alias}.luau")), base_folder.join(format!("{alias}.luau")),
self.cas_dir(), self.cas_dir(),
@ -168,6 +169,7 @@ impl Project {
base_folder.join(format!("{alias}.bin.luau")), base_folder.join(format!("{alias}.bin.luau")),
self.cas_dir(), self.cas_dir(),
&generator::generate_bin_linking_module( &generator::generate_bin_linking_module(
&container_folder,
&generator::get_bin_require_path( &generator::get_bin_require_path(
&base_folder, &base_folder,
bin_file, bin_file,

View file

@ -14,7 +14,7 @@ use crate::cli::{
auth::get_token, auth::get_token,
config::read_config, config::read_config,
home_dir, home_dir,
scripts::update_scripts_folder, repos::update_repo_dependencies,
version::{check_for_updates, current_version, get_or_download_version, max_installed_version}, version::{check_for_updates, current_version, get_or_download_version, max_installed_version},
HOME_DIR, HOME_DIR,
}; };
@ -258,32 +258,18 @@ fn run() -> anyhow::Result<()> {
std::process::exit(status.code().unwrap()); std::process::exit(status.code().unwrap());
} }
match check_for_updates(&reqwest) { display_err(check_for_updates(&reqwest), " while checking for updates");
Ok(_) => {} display_err(
Err(e) => { update_repo_dependencies(&project),
println!( " while updating repository dependencies",
"{}",
format!("failed to check for updates: {e}\n\n").red().bold()
); );
}
}
match update_scripts_folder(&project) {
Ok(_) => {}
Err(e) => {
println!(
"{}",
format!("failed to update scripts: {e}\n\n").red().bold()
);
}
}
Cli::parse().subcommand.run(project, multi, reqwest) Cli::parse().subcommand.run(project, multi, reqwest)
} }
fn main() { fn display_err(result: anyhow::Result<()>, prefix: &str) {
if let Err(err) = run() { if let Err(err) = result {
eprintln!("{}: {err}\n", "error".red().bold()); eprintln!("{}: {err}\n", format!("error{prefix}").red().bold());
let cause = err.chain().skip(1).collect::<Vec<_>>(); let cause = err.chain().skip(1).collect::<Vec<_>>();
@ -309,7 +295,14 @@ fn main() {
eprintln!("\n{}: not captured", "backtrace".yellow().bold()); eprintln!("\n{}: not captured", "backtrace".yellow().bold());
} }
} }
}
}
fn main() {
let result = run();
let is_err = result.is_err();
display_err(result, "");
if is_err {
std::process::exit(1); std::process::exit(1);
} }
} }