improve build times by extracting asset opt into its own crate (#3273)
* improve build types by extracing asset opt as a dylib * dont use dylib, but let regular workspace caching do the heavy lifting * add prebuild to cli for better lock contention * hoist deps * disable slow tests * re-enable sequential, debug=0 for dev * use vfs for windows * dont cache on failure, fix windows vfs caceh * free disk space re-order * add clippy + fmt to windows channel * yoink makefile * proper rustfmt/clippy on toolchain * set incremental to zero since cargo-cache disables it
This commit is contained in:
1 parent
79a2f023e7
commit
1cbfcde6cd
25 files changed
+550
-554
No files matched your search
+1
-70
@@ -20,6 +20,7 @@ dioxus-core = { workspace = true, features = ["serialize"] }
|
||||
dioxus-core-types = { workspace = true }
|
||||
dioxus-devtools-types = { workspace = true }
|
||||
dioxus-cli-config = { workspace = true }
|
||||
dioxus-cli-opt = { workspace = true }
|
||||
dioxus-fullstack = { workspace = true }
|
||||
dioxus-dx-wire-format = { workspace = true }
|
||||
|
||||
@@ -90,76 +91,6 @@ ignore = "0.4.22"
|
||||
env_logger = { workspace = true }
|
||||
const-serialize = { workspace = true, features = ["serde"] }
|
||||
|
||||
# Image compression/conversion
|
||||
# - JPEG
|
||||
mozjpeg = { version = "0.10.7", default-features = false, features = [
|
||||
"parallel",
|
||||
] }
|
||||
# - PNG
|
||||
imagequant = "4.2.0"
|
||||
png = "0.17.9"
|
||||
# Image format/conversion
|
||||
image = { version = "0.25", features = ["avif"] }
|
||||
|
||||
# CSS Minification
|
||||
lightningcss = "1.0.0-alpha.60"
|
||||
|
||||
# Js minification - swc has introduces minor versions with breaking changes in the past so we pin all of their crates
|
||||
swc = "=0.283.0"
|
||||
swc_allocator = { version = "=0.1.8", default-features = false }
|
||||
swc_atoms = { version = "=0.6.7", default-features = false }
|
||||
swc_cached = { version = "=0.3.20", default-features = false }
|
||||
swc_common = { version = "=0.37.5", default-features = false }
|
||||
swc_compiler_base = { version = "=0.19.0", default-features = false }
|
||||
swc_config = { version = "=0.1.15", default-features = false }
|
||||
swc_config_macro = { version = "=0.1.4", default-features = false }
|
||||
swc_ecma_ast = { version = "=0.118.2", default-features = false }
|
||||
swc_ecma_codegen = { version = "=0.155.1", default-features = false }
|
||||
swc_ecma_codegen_macros = { version = "=0.7.7", default-features = false }
|
||||
swc_ecma_compat_bugfixes = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_common = { version = "=0.11.0", default-features = false }
|
||||
swc_ecma_compat_es2015 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2016 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2017 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2018 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2019 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2020 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2021 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es2022 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_compat_es3 = { version = "=0.12.0", default-features = false }
|
||||
swc_ecma_ext_transforms = { version = "=0.120.0", default-features = false }
|
||||
swc_ecma_lints = { version = "=0.100.0", default-features = false }
|
||||
swc_ecma_loader = { version = "=0.49.1", default-features = false }
|
||||
swc_ecma_minifier = { version = "=0.204.0", default-features = false }
|
||||
swc_ecma_parser = { version = "=0.149.1", default-features = false }
|
||||
swc_ecma_preset_env = { version = "=0.217.0", default-features = false, features = [
|
||||
"serde",
|
||||
] }
|
||||
swc_ecma_transforms = { version = "=0.239.0", default-features = false }
|
||||
swc_ecma_transforms_base = { version = "=0.145.0", default-features = false }
|
||||
swc_ecma_transforms_classes = { version = "=0.134.0", default-features = false }
|
||||
swc_ecma_transforms_compat = { version = "=0.171.0", default-features = false }
|
||||
swc_ecma_transforms_macros = { version = "=0.5.5", default-features = false }
|
||||
swc_ecma_transforms_module = { version = "=0.190.0", default-features = false }
|
||||
swc_ecma_transforms_optimization = { version = "=0.208.0", default-features = false }
|
||||
swc_ecma_transforms_proposal = { version = "=0.178.0", default-features = false }
|
||||
swc_ecma_transforms_react = { version = "=0.191.0", default-features = false }
|
||||
swc_ecma_transforms_typescript = { version = "=0.198.1", default-features = false }
|
||||
swc_ecma_usage_analyzer = { version = "=0.30.3", default-features = false }
|
||||
swc_ecma_utils = { version = "=0.134.2", default-features = false }
|
||||
swc_ecma_visit = { version = "=0.104.8", default-features = false }
|
||||
swc_eq_ignore_macros = { version = "=0.1.4", default-features = false }
|
||||
swc_error_reporters = { version = "=0.21.0", default-features = false }
|
||||
swc_fast_graph = { version = "=0.25.0", default-features = false }
|
||||
swc_macros_common = { version = "=0.3.13", default-features = false }
|
||||
swc_node_comments = { version = "=0.24.0", default-features = false }
|
||||
swc_timer = { version = "=0.25.0", default-features = false }
|
||||
swc_trace_macro = { version = "=0.1.3", default-features = false }
|
||||
swc_transform_common = { version = "=0.1.1", default-features = false }
|
||||
swc_typescript = { version = "=0.5.0", default-features = false }
|
||||
swc_visit = { version = "=0.6.2", default-features = false }
|
||||
browserslist-rs = { version = "=0.16.0" }
|
||||
|
||||
tracing-subscriber = { version = "0.3.18", features = ["std", "env-filter", "json"] }
|
||||
console-subscriber = { version = "0.3.0", optional = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Context;
|
||||
use lightningcss::{
|
||||
printer::PrinterOptions,
|
||||
stylesheet::{MinifyOptions, ParserOptions, StyleSheet},
|
||||
};
|
||||
use manganis_core::CssAssetOptions;
|
||||
|
||||
pub(crate) fn process_css(
|
||||
css_options: &CssAssetOptions,
|
||||
source: &Path,
|
||||
output_path: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
let css = std::fs::read_to_string(source)?;
|
||||
|
||||
let css = if css_options.minified() {
|
||||
minify_css(&css)
|
||||
} else {
|
||||
css
|
||||
};
|
||||
|
||||
std::fs::write(output_path, css).with_context(|| {
|
||||
format!(
|
||||
"Failed to write css to output location: {}",
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn minify_css(css: &str) -> String {
|
||||
let mut stylesheet = StyleSheet::parse(css, ParserOptions::default()).unwrap();
|
||||
stylesheet.minify(MinifyOptions::default()).unwrap();
|
||||
let printer = PrinterOptions {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
};
|
||||
let res = stylesheet.to_css(printer).unwrap();
|
||||
res.code
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
use anyhow::Context;
|
||||
use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
|
||||
use std::path::Path;
|
||||
|
||||
use super::{
|
||||
css::process_css, folder::process_folder, image::process_image, js::process_js,
|
||||
json::process_json,
|
||||
};
|
||||
|
||||
/// Process a specific file asset with the given options reading from the source and writing to the output path
|
||||
pub(crate) fn process_file_to(
|
||||
options: &AssetOptions,
|
||||
source: &Path,
|
||||
output_path: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
// If the file already exists, then we must have a file with the same hash
|
||||
// already. The hash has the file contents and options, so if we find a file
|
||||
// with the same hash, we probably already created this file in the past
|
||||
if output_path.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(parent) = output_path.parent() {
|
||||
if !parent.exists() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
}
|
||||
match options {
|
||||
AssetOptions::Unknown => match source.extension().map(|e| e.to_string_lossy()).as_deref() {
|
||||
Some("css") => {
|
||||
process_css(&CssAssetOptions::new(), source, output_path)?;
|
||||
}
|
||||
Some("js") => {
|
||||
process_js(&JsAssetOptions::new(), source, output_path)?;
|
||||
}
|
||||
Some("json") => {
|
||||
process_json(source, output_path)?;
|
||||
}
|
||||
Some("jpg" | "jpeg" | "png" | "webp" | "avif") => {
|
||||
process_image(&ImageAssetOptions::new(), source, output_path)?;
|
||||
}
|
||||
Some(_) | None => {
|
||||
if source.is_dir() {
|
||||
process_folder(source, output_path)?;
|
||||
} else {
|
||||
let source_file = std::fs::File::open(source)?;
|
||||
let mut reader = std::io::BufReader::new(source_file);
|
||||
let output_file = std::fs::File::create(output_path)?;
|
||||
let mut writer = std::io::BufWriter::new(output_file);
|
||||
std::io::copy(&mut reader, &mut writer).with_context(|| {
|
||||
format!(
|
||||
"Failed to write file to output location: {}",
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
},
|
||||
AssetOptions::Css(options) => {
|
||||
process_css(options, source, output_path)?;
|
||||
}
|
||||
AssetOptions::Js(options) => {
|
||||
process_js(options, source, output_path)?;
|
||||
}
|
||||
AssetOptions::Image(options) => {
|
||||
process_image(options, source, output_path)?;
|
||||
}
|
||||
AssetOptions::Folder(_) => {
|
||||
process_folder(source, output_path)?;
|
||||
}
|
||||
_ => {
|
||||
tracing::warn!("Unknown asset options: {:?}", options);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
|
||||
use super::file::process_file_to;
|
||||
|
||||
/// Process a folder, optimizing and copying all assets into the output folder
|
||||
pub fn process_folder(source: &Path, output_folder: &Path) -> anyhow::Result<()> {
|
||||
// Create the folder
|
||||
std::fs::create_dir_all(output_folder)?;
|
||||
|
||||
// Then optimize children
|
||||
let files: Vec<_> = std::fs::read_dir(source)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
files.par_iter().try_for_each(|file| {
|
||||
let file = file.path();
|
||||
let metadata = file.metadata()?;
|
||||
let output_path = output_folder.join(file.strip_prefix(source)?);
|
||||
if metadata.is_dir() {
|
||||
process_folder(&file, &output_path)
|
||||
} else {
|
||||
process_file_minimal(&file, &output_path)
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Optimize a file without changing any of its contents significantly (e.g. by changing the extension)
|
||||
fn process_file_minimal(input_path: &Path, output_path: &Path) -> anyhow::Result<()> {
|
||||
process_file_to(
|
||||
&manganis_core::AssetOptions::Unknown,
|
||||
input_path,
|
||||
output_path,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
use image::{DynamicImage, EncodableLayout};
|
||||
use std::{
|
||||
io::{BufWriter, Write},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
pub(crate) fn compress_jpg(image: DynamicImage, output_location: &Path) -> anyhow::Result<()> {
|
||||
let mut comp = mozjpeg::Compress::new(mozjpeg::ColorSpace::JCS_EXT_RGBX);
|
||||
let width = image.width() as usize;
|
||||
let height = image.height() as usize;
|
||||
|
||||
comp.set_size(width, height);
|
||||
let mut comp = comp.start_compress(Vec::new())?; // any io::Write will work
|
||||
|
||||
comp.write_scanlines(image.to_rgba8().as_bytes())?;
|
||||
|
||||
let jpeg_bytes = comp.finish()?;
|
||||
|
||||
let file = std::fs::File::create(output_location)?;
|
||||
let w = &mut BufWriter::new(file);
|
||||
w.write_all(&jpeg_bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Context;
|
||||
use jpg::compress_jpg;
|
||||
use manganis_core::{ImageAssetOptions, ImageFormat, ImageSize};
|
||||
use png::compress_png;
|
||||
|
||||
mod jpg;
|
||||
mod png;
|
||||
|
||||
pub(crate) fn process_image(
|
||||
image_options: &ImageAssetOptions,
|
||||
source: &Path,
|
||||
output_path: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut image = image::ImageReader::new(std::io::Cursor::new(&*std::fs::read(source)?))
|
||||
.with_guessed_format()?
|
||||
.decode();
|
||||
|
||||
if let Ok(image) = &mut image {
|
||||
if let ImageSize::Manual { width, height } = image_options.size() {
|
||||
*image = image.resize_exact(width, height, image::imageops::FilterType::Lanczos3);
|
||||
}
|
||||
}
|
||||
|
||||
match (image, image_options.format()) {
|
||||
(image, ImageFormat::Png) => {
|
||||
compress_png(image?, output_path);
|
||||
}
|
||||
(image, ImageFormat::Jpg) => {
|
||||
compress_jpg(image?, output_path)?;
|
||||
}
|
||||
(Ok(image), ImageFormat::Avif) => {
|
||||
if let Err(error) = image.save(output_path) {
|
||||
tracing::error!("Failed to save avif image: {} with path {}. You must have the avif feature enabled to use avif assets", error, output_path.display());
|
||||
}
|
||||
}
|
||||
(Ok(image), ImageFormat::Webp) => {
|
||||
if let Err(err) = image.save(output_path) {
|
||||
tracing::error!("Failed to save webp image: {}. You must have the avif feature enabled to use webp assets", err);
|
||||
}
|
||||
}
|
||||
(Ok(image), _) => {
|
||||
image.save(output_path)?;
|
||||
}
|
||||
// If we can't decode the image or it is of an unknown type, we just copy the file
|
||||
_ => {
|
||||
let source_file = std::fs::File::open(source)?;
|
||||
let mut reader = std::io::BufReader::new(source_file);
|
||||
let output_file = std::fs::File::create(output_path)?;
|
||||
let mut writer = std::io::BufWriter::new(output_file);
|
||||
std::io::copy(&mut reader, &mut writer).with_context(|| {
|
||||
format!(
|
||||
"Failed to write image to output location: {}",
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
use std::{io::BufWriter, path::Path};
|
||||
|
||||
use image::DynamicImage;
|
||||
|
||||
pub(crate) fn compress_png(image: DynamicImage, output_location: &Path) {
|
||||
// Image loading/saving is outside scope of this library
|
||||
let width = image.width() as usize;
|
||||
let height = image.height() as usize;
|
||||
let bitmap: Vec<_> = image
|
||||
.into_rgba8()
|
||||
.pixels()
|
||||
.map(|px| imagequant::RGBA::new(px[0], px[1], px[2], px[3]))
|
||||
.collect();
|
||||
|
||||
// Configure the library
|
||||
let mut liq = imagequant::new();
|
||||
liq.set_speed(5).unwrap();
|
||||
liq.set_quality(0, 99).unwrap();
|
||||
|
||||
// Describe the bitmap
|
||||
let mut img = liq.new_image(&bitmap[..], width, height, 0.0).unwrap();
|
||||
|
||||
// The magic happens in quantize()
|
||||
let mut res = match liq.quantize(&mut img) {
|
||||
Ok(res) => res,
|
||||
Err(err) => panic!("Quantization failed, because: {err:?}"),
|
||||
};
|
||||
|
||||
let (palette, pixels) = res.remapped(&mut img).unwrap();
|
||||
|
||||
let file = std::fs::File::create(output_location).unwrap();
|
||||
let w = &mut BufWriter::new(file);
|
||||
|
||||
let mut encoder = png::Encoder::new(w, width as u32, height as u32);
|
||||
encoder.set_color(png::ColorType::Rgba);
|
||||
let mut flattened_palette = Vec::new();
|
||||
let mut alpha_palette = Vec::new();
|
||||
for px in palette {
|
||||
flattened_palette.push(px.r);
|
||||
flattened_palette.push(px.g);
|
||||
flattened_palette.push(px.b);
|
||||
alpha_palette.push(px.a);
|
||||
}
|
||||
encoder.set_palette(flattened_palette);
|
||||
encoder.set_trns(alpha_palette);
|
||||
encoder.set_depth(png::BitDepth::Eight);
|
||||
encoder.set_color(png::ColorType::Indexed);
|
||||
encoder.set_compression(png::Compression::Best);
|
||||
let mut writer = encoder.write_header().unwrap();
|
||||
writer.write_image_data(&pixels).unwrap();
|
||||
writer.finish().unwrap();
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Context;
|
||||
use manganis_core::JsAssetOptions;
|
||||
use swc::{config::JsMinifyOptions, try_with_handler, BoolOrDataConfig};
|
||||
use swc_common::{sync::Lrc, FileName};
|
||||
use swc_common::{SourceMap, GLOBALS};
|
||||
|
||||
pub(crate) fn minify_js(source: &Path) -> anyhow::Result<String> {
|
||||
let mut source_file = std::fs::File::open(source)?;
|
||||
let cm = Arc::new(SourceMap::default());
|
||||
|
||||
let mut js = String::new();
|
||||
source_file.read_to_string(&mut js)?;
|
||||
let c = swc::Compiler::new(cm.clone());
|
||||
let output = GLOBALS
|
||||
.set(&Default::default(), || {
|
||||
try_with_handler(cm.clone(), Default::default(), |handler| {
|
||||
let filename = Lrc::new(FileName::Real(source.to_path_buf()));
|
||||
let fm = cm.new_source_file(filename, js.to_string());
|
||||
|
||||
c.minify(
|
||||
fm,
|
||||
handler,
|
||||
&JsMinifyOptions {
|
||||
compress: BoolOrDataConfig::from_bool(true),
|
||||
mangle: BoolOrDataConfig::from_bool(true),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.context("failed to minify javascript")
|
||||
})
|
||||
})
|
||||
.map(|output| output.code);
|
||||
|
||||
match output {
|
||||
Ok(output) => Ok(output),
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to minify javascript: {}", err);
|
||||
Ok(js)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn process_js(
|
||||
js_options: &JsAssetOptions,
|
||||
source: &Path,
|
||||
output_path: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
let js = if js_options.minified() {
|
||||
minify_js(source)?
|
||||
} else {
|
||||
let mut source_file = std::fs::File::open(source)?;
|
||||
let mut source = String::new();
|
||||
source_file.read_to_string(&mut source)?;
|
||||
source
|
||||
};
|
||||
|
||||
std::fs::write(output_path, js).with_context(|| {
|
||||
format!(
|
||||
"Failed to write js to output location: {}",
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
use std::{io::Read, path::Path};
|
||||
|
||||
use anyhow::Context;
|
||||
|
||||
pub(crate) fn minify_json(source: &str) -> anyhow::Result<String> {
|
||||
// First try to parse the json
|
||||
let json: serde_json::Value = serde_json::from_str(source)?;
|
||||
// Then print it in a minified format
|
||||
let json = serde_json::to_string(&json)?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
pub(crate) fn process_json(source: &Path, output_path: &Path) -> anyhow::Result<()> {
|
||||
let mut source_file = std::fs::File::open(source)?;
|
||||
let mut source = String::new();
|
||||
source_file.read_to_string(&mut source)?;
|
||||
let json = match minify_json(&source) {
|
||||
Ok(json) => json,
|
||||
Err(err) => {
|
||||
tracing::error!("Failed to minify json: {}", err);
|
||||
source
|
||||
}
|
||||
};
|
||||
|
||||
std::fs::write(output_path, json).with_context(|| {
|
||||
format!(
|
||||
"Failed to write json to output location: {}",
|
||||
output_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
use anyhow::Context;
|
||||
use manganis_core::linker::LinkSection;
|
||||
use manganis_core::BundledAsset;
|
||||
use object::{read::archive::ArchiveFile, File as ObjectFile, Object, ObjectSection};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
mod css;
|
||||
mod file;
|
||||
mod folder;
|
||||
mod image;
|
||||
mod js;
|
||||
mod json;
|
||||
|
||||
pub(crate) use file::process_file_to;
|
||||
|
||||
/// A manifest of all assets collected from dependencies
|
||||
///
|
||||
/// This will be filled in primarily by incremental compilation artifacts.
|
||||
#[derive(Debug, PartialEq, Default, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct AssetManifest {
|
||||
/// Map of bundled asset name to the asset itself
|
||||
pub(crate) assets: HashMap<PathBuf, BundledAsset>,
|
||||
}
|
||||
|
||||
impl AssetManifest {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn load_from_file(path: &Path) -> anyhow::Result<Self> {
|
||||
let src = std::fs::read_to_string(path)?;
|
||||
|
||||
serde_json::from_str(&src)
|
||||
.with_context(|| format!("Failed to parse asset manifest from {path:?}\n{src}"))
|
||||
}
|
||||
|
||||
/// Fill this manifest with a file object/rlib files, typically extracted from the linker intercepted
|
||||
pub(crate) fn add_from_object_path(&mut self, path: &Path) -> anyhow::Result<()> {
|
||||
let data = std::fs::read(path)?;
|
||||
|
||||
match path.extension().and_then(|ext| ext.to_str()) {
|
||||
// Parse an rlib as a collection of objects
|
||||
Some("rlib") => {
|
||||
if let Ok(archive) = object::read::archive::ArchiveFile::parse(&*data) {
|
||||
self.add_from_archive_file(&archive, &data)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Ok(object) = object::File::parse(&*data) {
|
||||
self.add_from_object_file(&object)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fill this manifest from an rlib / ar file that contains many object files and their entries
|
||||
fn add_from_archive_file(&mut self, archive: &ArchiveFile, data: &[u8]) -> object::Result<()> {
|
||||
// Look through each archive member for object files.
|
||||
// Read the archive member's binary data (we know it's an object file)
|
||||
// And parse it with the normal `object::File::parse` to find the manganis string.
|
||||
for member in archive.members() {
|
||||
let member = member?;
|
||||
let name = String::from_utf8_lossy(member.name()).to_string();
|
||||
|
||||
// Check if the archive member is an object file and parse it.
|
||||
if name.ends_with(".o") {
|
||||
let data = member.data(data)?;
|
||||
let object = object::File::parse(data)?;
|
||||
_ = self.add_from_object_file(&object);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fill this manifest with whatever tables might come from the object file
|
||||
fn add_from_object_file(&mut self, obj: &ObjectFile) -> anyhow::Result<()> {
|
||||
for section in obj.sections() {
|
||||
let Ok(section_name) = section.name() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Check if the link section matches the asset section for one of the platforms we support. This may not be the current platform if the user is cross compiling
|
||||
let matches = LinkSection::ALL
|
||||
.iter()
|
||||
.any(|x| x.link_section == section_name);
|
||||
|
||||
if !matches {
|
||||
continue;
|
||||
}
|
||||
|
||||
let bytes = section
|
||||
.uncompressed_data()
|
||||
.context("Could not read uncompressed data from object file")?;
|
||||
|
||||
let mut buffer = const_serialize::ConstReadBuffer::new(&bytes);
|
||||
while let Some((remaining_buffer, asset)) =
|
||||
const_serialize::deserialize_const!(BundledAsset, buffer)
|
||||
{
|
||||
self.assets
|
||||
.insert(asset.absolute_source_path().into(), asset);
|
||||
buffer = remaining_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::assets::process_file_to;
|
||||
use crate::Result;
|
||||
use crate::{assets::AssetManifest, TraceSrc};
|
||||
use crate::{BuildRequest, Platform};
|
||||
use crate::{Result, TraceSrc};
|
||||
use anyhow::Context;
|
||||
use dioxus_cli_opt::{process_file_to, AssetManifest};
|
||||
use manganis_core::AssetOptions;
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use super::{progress::ProgressTx, BuildArtifacts};
|
||||
use crate::dioxus_crate::DioxusCrate;
|
||||
use crate::Result;
|
||||
use crate::{assets::AssetManifest, TraceSrc};
|
||||
use crate::{link::LinkAction, BuildArgs};
|
||||
use crate::{AppBundle, Platform};
|
||||
use crate::{AppBundle, Platform, Result, TraceSrc};
|
||||
use anyhow::Context;
|
||||
use dioxus_cli_config::{APP_TITLE_ENV, ASSET_ROOT_ENV};
|
||||
use dioxus_cli_opt::AssetManifest;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
@@ -46,7 +45,10 @@ impl BuildRequest {
|
||||
pub(crate) async fn build_all(self) -> Result<AppBundle> {
|
||||
tracing::debug!("Running build command...");
|
||||
|
||||
let (app, server) = self.build_concurrent().await?;
|
||||
let (app, server) = match self.build.force_sequential {
|
||||
true => self.build_sequential().await?,
|
||||
false => self.build_concurrent().await?,
|
||||
};
|
||||
|
||||
AppBundle::new(self, app, server).await
|
||||
}
|
||||
@@ -59,6 +61,12 @@ impl BuildRequest {
|
||||
Ok((app, server))
|
||||
}
|
||||
|
||||
async fn build_sequential(&self) -> Result<(BuildArtifacts, Option<BuildArtifacts>)> {
|
||||
let app = self.build_app().await?;
|
||||
let server = self.build_server().await?;
|
||||
Ok((app, server))
|
||||
}
|
||||
|
||||
pub(crate) async fn build_app(&self) -> Result<BuildArtifacts> {
|
||||
tracing::debug!("Building app...");
|
||||
|
||||
|
||||
+159
-157
@@ -223,191 +223,193 @@ fn remove_triple_newlines(string: &str) -> String {
|
||||
new_string
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use escargot::{CargoBuild, CargoRun};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::fs::{create_dir_all, read_to_string};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use tempfile::tempdir;
|
||||
use toml::Value;
|
||||
// todo: re-enable these tests with better parallelization
|
||||
//
|
||||
// #[cfg(test)]
|
||||
// pub(crate) mod tests {
|
||||
// use escargot::{CargoBuild, CargoRun};
|
||||
// use once_cell::sync::Lazy;
|
||||
// use std::fs::{create_dir_all, read_to_string};
|
||||
// use std::path::{Path, PathBuf};
|
||||
// use std::process::Command;
|
||||
// use tempfile::tempdir;
|
||||
// use toml::Value;
|
||||
|
||||
static BINARY: Lazy<CargoRun> = Lazy::new(|| {
|
||||
CargoBuild::new()
|
||||
.bin(env!("CARGO_BIN_NAME"))
|
||||
.current_release()
|
||||
.run()
|
||||
.expect("Couldn't build the binary for tests.")
|
||||
});
|
||||
// static BINARY: Lazy<CargoRun> = Lazy::new(|| {
|
||||
// CargoBuild::new()
|
||||
// .bin(env!("CARGO_BIN_NAME"))
|
||||
// .current_release()
|
||||
// .run()
|
||||
// .expect("Couldn't build the binary for tests.")
|
||||
// });
|
||||
|
||||
// Note: tests below (at least 6 of them) were written to mainly test
|
||||
// correctness of project's directory and its name, because previously it
|
||||
// was broken and tests bring a peace of mind. And also so that I don't have
|
||||
// to run my local hand-made tests every time.
|
||||
// // Note: tests below (at least 6 of them) were written to mainly test
|
||||
// // correctness of project's directory and its name, because previously it
|
||||
// // was broken and tests bring a peace of mind. And also so that I don't have
|
||||
// // to run my local hand-made tests every time.
|
||||
|
||||
pub(crate) type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
// pub(crate) type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
pub(crate) fn subcommand(name: &str) -> Command {
|
||||
let mut command = BINARY.command();
|
||||
command.arg(name).arg("--yes"); // Skip any questions by choosing default answers.
|
||||
command
|
||||
}
|
||||
// pub(crate) fn subcommand(name: &str) -> Command {
|
||||
// let mut command = BINARY.command();
|
||||
// command.arg(name).arg("--yes"); // Skip any questions by choosing default answers.
|
||||
// command
|
||||
// }
|
||||
|
||||
pub(crate) fn get_cargo_toml_path(project_path: &Path) -> PathBuf {
|
||||
project_path.join("Cargo.toml")
|
||||
}
|
||||
// pub(crate) fn get_cargo_toml_path(project_path: &Path) -> PathBuf {
|
||||
// project_path.join("Cargo.toml")
|
||||
// }
|
||||
|
||||
pub(crate) fn get_project_name(cargo_toml_path: &Path) -> Result<String> {
|
||||
Ok(toml::from_str::<Value>(&read_to_string(cargo_toml_path)?)?
|
||||
.get("package")
|
||||
.unwrap()
|
||||
.get("name")
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string())
|
||||
}
|
||||
// pub(crate) fn get_project_name(cargo_toml_path: &Path) -> Result<String> {
|
||||
// Ok(toml::from_str::<Value>(&read_to_string(cargo_toml_path)?)?
|
||||
// .get("package")
|
||||
// .unwrap()
|
||||
// .get("name")
|
||||
// .unwrap()
|
||||
// .as_str()
|
||||
// .unwrap()
|
||||
// .to_string())
|
||||
// }
|
||||
|
||||
fn subcommand_new() -> Command {
|
||||
subcommand("new")
|
||||
}
|
||||
// fn subcommand_new() -> Command {
|
||||
// subcommand("new")
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_dot_path() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = project_dir;
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_dot_path() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = project_dir;
|
||||
|
||||
let temp_dir = tempdir()?;
|
||||
// Make current dir's name deterministic.
|
||||
let current_dir = temp_dir.path().join(project_dir);
|
||||
create_dir_all(¤t_dir)?;
|
||||
let project_path = ¤t_dir;
|
||||
assert!(project_path.exists());
|
||||
// let temp_dir = tempdir()?;
|
||||
// // Make current dir's name deterministic.
|
||||
// let current_dir = temp_dir.path().join(project_dir);
|
||||
// create_dir_all(¤t_dir)?;
|
||||
// let project_path = ¤t_dir;
|
||||
// assert!(project_path.exists());
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg(".")
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg(".")
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_1_dir_path() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = project_dir;
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_1_dir_path() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = project_dir;
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg(project_dir)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg(project_dir)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_2_dir_path() -> Result<()> {
|
||||
let project_dir = "a/b";
|
||||
let project_name = "b";
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_2_dir_path() -> Result<()> {
|
||||
// let project_dir = "a/b";
|
||||
// let project_name = "b";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg(project_dir)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg(project_dir)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_dot_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_dot_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = "project";
|
||||
|
||||
let temp_dir = tempdir()?;
|
||||
// Make current dir's name deterministic.
|
||||
let current_dir = temp_dir.path().join(project_dir);
|
||||
create_dir_all(¤t_dir)?;
|
||||
let project_path = ¤t_dir;
|
||||
assert!(project_path.exists());
|
||||
// let temp_dir = tempdir()?;
|
||||
// // Make current dir's name deterministic.
|
||||
// let current_dir = temp_dir.path().join(project_dir);
|
||||
// create_dir_all(¤t_dir)?;
|
||||
// let project_path = ¤t_dir;
|
||||
// assert!(project_path.exists());
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.arg(".")
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .arg(".")
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_1_dir_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_1_dir_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = "project";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg(project_dir)
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg(project_dir)
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_new_with_2_dir_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "a/b";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_new_with_2_dir_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "a/b";
|
||||
// let project_name = "project";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_new()
|
||||
.arg(project_dir)
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_new()
|
||||
// .arg(project_dir)
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
+124
-122
@@ -78,152 +78,154 @@ impl Init {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs::create_dir_all, process::Command};
|
||||
use tempfile::tempdir;
|
||||
// todo: re-enable these tests with better parallelization
|
||||
//
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use std::{fs::create_dir_all, process::Command};
|
||||
// use tempfile::tempdir;
|
||||
|
||||
use super::create::tests::*;
|
||||
// use super::create::tests::*;
|
||||
|
||||
// Note: tests below (at least 6 of them) were written to mainly test
|
||||
// correctness of project's directory and its name, because previously it
|
||||
// was broken and tests bring a peace of mind. And also so that I don't have
|
||||
// to run my local hand-made tests every time.
|
||||
// // Note: tests below (at least 6 of them) were written to mainly test
|
||||
// // correctness of project's directory and its name, because previously it
|
||||
// // was broken and tests bring a peace of mind. And also so that I don't have
|
||||
// // to run my local hand-made tests every time.
|
||||
|
||||
fn subcommand_init() -> Command {
|
||||
subcommand("init")
|
||||
}
|
||||
// fn subcommand_init() -> Command {
|
||||
// subcommand("init")
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_default_path() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = project_dir;
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_default_path() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = project_dir;
|
||||
|
||||
let temp_dir = tempdir()?;
|
||||
// Make current dir's name deterministic.
|
||||
let current_dir = temp_dir.path().join(project_dir);
|
||||
create_dir_all(¤t_dir)?;
|
||||
let project_path = ¤t_dir;
|
||||
assert!(project_path.exists());
|
||||
// let temp_dir = tempdir()?;
|
||||
// // Make current dir's name deterministic.
|
||||
// let current_dir = temp_dir.path().join(project_dir);
|
||||
// create_dir_all(¤t_dir)?;
|
||||
// let project_path = ¤t_dir;
|
||||
// assert!(project_path.exists());
|
||||
|
||||
assert!(subcommand_init().current_dir(¤t_dir).status().is_ok());
|
||||
// assert!(subcommand_init().current_dir(¤t_dir).status().is_ok());
|
||||
|
||||
let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_1_dir_path() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = project_dir;
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_1_dir_path() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = project_dir;
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_init()
|
||||
.arg(project_dir)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_init()
|
||||
// .arg(project_dir)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_2_dir_path() -> Result<()> {
|
||||
let project_dir = "a/b";
|
||||
let project_name = "b";
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_2_dir_path() -> Result<()> {
|
||||
// let project_dir = "a/b";
|
||||
// let project_name = "b";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_init()
|
||||
.arg(project_dir)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_init()
|
||||
// .arg(project_dir)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_default_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_default_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = "project";
|
||||
|
||||
let temp_dir = tempdir()?;
|
||||
// Make current dir's name deterministic.
|
||||
let current_dir = temp_dir.path().join(project_dir);
|
||||
create_dir_all(¤t_dir)?;
|
||||
let project_path = ¤t_dir;
|
||||
assert!(project_path.exists());
|
||||
// let temp_dir = tempdir()?;
|
||||
// // Make current dir's name deterministic.
|
||||
// let current_dir = temp_dir.path().join(project_dir);
|
||||
// create_dir_all(¤t_dir)?;
|
||||
// let project_path = ¤t_dir;
|
||||
// assert!(project_path.exists());
|
||||
|
||||
assert!(subcommand_init()
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_init()
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let cargo_toml_path = get_cargo_toml_path(project_path);
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_1_dir_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "dir";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_1_dir_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "dir";
|
||||
// let project_name = "project";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_init()
|
||||
.arg(project_dir)
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_init()
|
||||
// .arg(project_dir)
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_subcommand_init_with_2_dir_path_and_custom_name() -> Result<()> {
|
||||
let project_dir = "a/b";
|
||||
let project_name = "project";
|
||||
// #[test]
|
||||
// fn test_subcommand_init_with_2_dir_path_and_custom_name() -> Result<()> {
|
||||
// let project_dir = "a/b";
|
||||
// let project_name = "project";
|
||||
|
||||
let current_dir = tempdir()?;
|
||||
// let current_dir = tempdir()?;
|
||||
|
||||
assert!(subcommand_init()
|
||||
.arg(project_dir)
|
||||
.arg("--name")
|
||||
.arg(project_name)
|
||||
.current_dir(¤t_dir)
|
||||
.status()
|
||||
.is_ok());
|
||||
// assert!(subcommand_init()
|
||||
// .arg(project_dir)
|
||||
// .arg("--name")
|
||||
// .arg(project_name)
|
||||
// .current_dir(¤t_dir)
|
||||
// .status()
|
||||
// .is_ok());
|
||||
|
||||
let project_path = current_dir.path().join(project_dir);
|
||||
let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
assert!(project_path.exists());
|
||||
assert!(cargo_toml_path.exists());
|
||||
assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// let project_path = current_dir.path().join(project_dir);
|
||||
// let cargo_toml_path = get_cargo_toml_path(&project_path);
|
||||
// assert!(project_path.exists());
|
||||
// assert!(cargo_toml_path.exists());
|
||||
// assert_eq!(get_project_name(&cargo_toml_path)?, project_name);
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::assets::AssetManifest;
|
||||
use dioxus_cli_opt::AssetManifest;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
mod assets;
|
||||
mod build;
|
||||
mod bundle_utils;
|
||||
mod cli;
|
||||
|
||||
Reference in new issue
Block a user