Skip to content

Commit

Permalink
fix very long file names
Browse files Browse the repository at this point in the history
  • Loading branch information
ealmloff committed Feb 19, 2024
1 parent 81f84c5 commit be623ca
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 65 deletions.
4 changes: 2 additions & 2 deletions cli-support/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ impl Process for ImageOptions {
}
ImageType::Avif => {
output_location.push(input_location.unique_name());
if let Err(error) = image.save(output_location) {
tracing::error!("Failed to save avif image: {}. You must have the avif feature enabled to use avif assets", error);
if let Err(error) = image.save(&output_location) {
tracing::error!("Failed to save avif image: {} with path {}. You must have the avif feature enabled to use avif assets", error, output_location.display());
}
}
ImageType::Webp => {
Expand Down
103 changes: 59 additions & 44 deletions common/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,10 @@ impl FromStr for FileSource {
Err(_) => {
let manifest_dir = manifest_dir();
let path = manifest_dir.join(PathBuf::from(s));
Ok(Self::Local(path.canonicalize()?))
let path = path
.canonicalize()
.with_context(|| format!("Failed to canonicalize path: {}", path.display()))?;
Ok(Self::Local(path))
}
}
}
Expand All @@ -264,56 +267,32 @@ impl FileAsset {
/// Creates a new file asset
pub fn new(source: FileSource) -> Self {
let options = FileOptions::default_for_extension(source.extension().as_deref());
let manifest_dir = manifest_dir();
let path = manifest_dir.join(source.last_segment());
let updated = source.last_updated();
let file_name = path.file_stem().unwrap().to_string_lossy();
let extension = options
.extension()
.map(|e| format!(".{e}"))
.unwrap_or_default();
let mut hash = std::collections::hash_map::DefaultHasher::new();
updated.hash(&mut hash);
options.hash(&mut hash);
source.hash(&mut hash);
let uuid = hash.finish();
let unique_name = format!("{file_name}{uuid}{extension}");

Self {
let mut myself = Self {
location: FileLocation {
unique_name,
unique_name: Default::default(),
source,
},
options,
url_encoded: false,
}
};

myself.regenerate_unique_name();

myself
}

/// Set the file options
pub fn with_options(self, options: FileOptions) -> Self {
let manifest_dir = manifest_dir();
let path = manifest_dir.join(self.location.source.last_segment());
let updated = self.location.source.last_updated();
let file_name = path.file_stem().unwrap().to_string_lossy();
let extension = options
.extension()
.map(|e| format!(".{e}"))
.unwrap_or_default();
let mut hash = std::collections::hash_map::DefaultHasher::new();
updated.hash(&mut hash);
options.hash(&mut hash);
self.location.source.hash(&mut hash);
let uuid = hash.finish();
let unique_name = format!("{file_name}{uuid}{extension}");

Self {
location: FileLocation {
unique_name,
source: self.location.source,
},
let mut myself = Self {
location: self.location,
options,
url_encoded: false,
}
};

myself.regenerate_unique_name();

myself
}

/// Set whether the file asset should be url encoded
Expand Down Expand Up @@ -346,11 +325,6 @@ impl FileAsset {
&self.location
}

/// Returns the location of the file asset
pub fn set_unique_name(&mut self, unique_name: &str) {
self.location.unique_name = unique_name.to_string();
}

/// Returns the options for the file asset
pub fn options(&self) -> &FileOptions {
&self.options
Expand All @@ -360,6 +334,47 @@ impl FileAsset {
pub fn options_mut(&mut self) -> &mut FileOptions {
&mut self.options
}

/// Regenerates the unique name of the file asset
fn regenerate_unique_name(&mut self) {
const MAX_PATH_LENGTH: usize = 128;
const HASH_SIZE: usize = 16;

let manifest_dir = manifest_dir();
let last_segment = self
.location
.source
.last_segment()
.chars()
.filter(|c| c.is_alphanumeric())
.collect::<String>();
let path = manifest_dir.join(last_segment);
let updated = self.location.source.last_updated();
let extension = self
.options
.extension()
.map(|e| format!(".{e}"))
.unwrap_or_default();
let extension_and_hash_size = extension.len() + HASH_SIZE;
let mut file_name = path
.file_stem()
.unwrap()
.to_string_lossy()
.chars()
.filter(|c| c.is_alphanumeric())
.collect::<String>();
// If the file name is too long, we need to truncate it
if file_name.len() + extension_and_hash_size > MAX_PATH_LENGTH {
file_name = file_name[..MAX_PATH_LENGTH - extension_and_hash_size].to_string();
}
let mut hash = std::collections::hash_map::DefaultHasher::new();
updated.hash(&mut hash);
self.options.hash(&mut hash);
self.location.source.hash(&mut hash);
let uuid = hash.finish();
self.location.unique_name = format!("{file_name}{uuid:x}{extension}");
assert!(self.location.unique_name.len() <= MAX_PATH_LENGTH);
}
}

/// A metadata asset
Expand Down
14 changes: 7 additions & 7 deletions common/src/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ use crate::{
};

/// Clears all assets from the current package
pub fn clear_assets() {
pub fn clear_assets() -> std::io::Result<()> {
let dir = current_package_cache_dir();
let _ = std::fs::remove_dir_all(dir);
std::fs::remove_dir_all(dir)
}

/// Adds an asset to the current package
pub fn add_asset(asset: AssetType) -> AssetType {
pub fn add_asset(asset: AssetType) -> std::io::Result<AssetType> {
let mut dir = current_package_cache_dir();
dir.push("assets.toml");
let mut package_assets: PackageAssets = if dir.exists() {
let contents = std::fs::read_to_string(&dir).unwrap();
let contents = std::fs::read_to_string(&dir)?;
toml::from_str(&contents).unwrap_or_else(|_| PackageAssets {
package: current_package_identifier(),
assets: vec![],
})
} else {
std::fs::create_dir_all(dir.parent().unwrap()).unwrap();
std::fs::create_dir_all(dir.parent().unwrap())?;
PackageAssets {
package: current_package_identifier(),
assets: vec![],
Expand All @@ -31,9 +31,9 @@ pub fn add_asset(asset: AssetType) -> AssetType {

package_assets.add(asset.clone());
let contents = toml::to_string(&package_assets).unwrap();
std::fs::write(&dir, contents).unwrap();
std::fs::write(&dir, contents)?;

asset
Ok(asset)
}

/// All assets collected from a specific package
Expand Down
8 changes: 7 additions & 1 deletion macro/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ impl Parse for FileAssetParser {
))
};
let this_file = FileAsset::new(path);
let asset = add_asset(manganis_common::AssetType::File(this_file.clone()));
let asset =
add_asset(manganis_common::AssetType::File(this_file.clone())).map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to add asset: {e}"),
)
})?;
let this_file = match asset {
manganis_common::AssetType::File(this_file) => this_file,
_ => unreachable!(),
Expand Down
8 changes: 7 additions & 1 deletion macro/src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ impl Parse for FontAssetParser {
};
let this_file = FileAsset::new(url.clone())
.with_options(manganis_common::FileOptions::Css(CssOptions::default()));
let asset = add_asset(manganis_common::AssetType::File(this_file.clone()));
let asset =
add_asset(manganis_common::AssetType::File(this_file.clone())).map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to add asset: {e}"),
)
})?;
let this_file = match asset {
manganis_common::AssetType::File(this_file) => this_file,
_ => unreachable!(),
Expand Down
8 changes: 7 additions & 1 deletion macro/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,13 @@ impl Parse for ImageAssetParser {
parsed_options.apply_to_options(&mut this_file, &mut low_quality_preview);
}

let asset = add_asset(manganis_common::AssetType::File(this_file.clone()));
let asset =
add_asset(manganis_common::AssetType::File(this_file.clone())).map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to add asset: {e}"),
)
})?;
let this_file = match asset {
manganis_common::AssetType::File(this_file) => this_file,
_ => unreachable!(),
Expand Down
42 changes: 33 additions & 9 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ mod image;
// We can reset the asset of the current crate the first time the macro is used in the crate.
static INITIALIZED: AtomicBool = AtomicBool::new(false);

fn add_asset(asset: manganis_common::AssetType) -> AssetType {
fn add_asset(asset: manganis_common::AssetType) -> std::io::Result<AssetType> {
if !INITIALIZED.load(Ordering::Relaxed) {
INITIALIZED.store(true, Ordering::Relaxed);
manganis_common::clear_assets();
manganis_common::clear_assets()?;
}

manganis_common::add_asset(asset)
Expand All @@ -41,12 +41,28 @@ pub fn classes(input: TokenStream) -> TokenStream {
let input_as_str = parse_macro_input!(input as LitStr);
let input_as_str = input_as_str.value();

add_asset(manganis_common::AssetType::Tailwind(TailwindAsset::new(
let result = add_asset(manganis_common::AssetType::Tailwind(TailwindAsset::new(
&input_as_str,
)));
)))
.map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to add asset: {e}"),
)
.into_compile_error()
});

let result = match result {
Ok(_) => quote! {
#input_as_str
},
Err(e) => quote! {
#e
},
};

quote! {
#input_as_str
#result
}
.into_token_stream()
.into()
Expand Down Expand Up @@ -170,10 +186,18 @@ impl Parse for MetadataValue {
pub fn meta(input: TokenStream) -> TokenStream {
let md = parse_macro_input!(input as MetadataValue);

add_asset(manganis_common::AssetType::Metadata(MetadataAsset::new(
let result = add_asset(manganis_common::AssetType::Metadata(MetadataAsset::new(
md.key.as_str(),
md.value.as_str(),
)));

quote! {}.into_token_stream().into()
)))
.map_err(|e| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("Failed to add asset: {e}"),
)
.into_compile_error()
})
.err();

quote! {#result}.into_token_stream().into()
}

0 comments on commit be623ca

Please sign in to comment.