mirror of
https://github.com/pesde-pkg/pesde.git
synced 2024-12-12 11:00:36 +00:00
feat: add PESDE_ROOT for bin packages
This commit is contained in:
parent
71eacb8673
commit
d321b8b0aa
10 changed files with 188 additions and 151 deletions
|
@ -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))
|
||||||
|
|
|
@ -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()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
114
src/cli/repos.rs
Normal 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(())
|
||||||
|
}
|
|
@ -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(())
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
.get(name)
|
if let Some((lib_file, types)) =
|
||||||
.and_then(|v| v.get(version_id))
|
node.target.lib_path().and_then(|lib_file| {
|
||||||
.and_then(|types| {
|
package_types
|
||||||
node.node.direct.as_ref().map(|(alias, _)| (alias, types))
|
.get(name)
|
||||||
})
|
.and_then(|v| v.get(version_id))
|
||||||
{
|
.map(|types| (lib_file, 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,
|
||||||
|
|
39
src/main.rs
39
src/main.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue