diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 2b9d685..a650253 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -167,7 +167,8 @@ jobs: context: . file: ./Dockerfile push: true - platforms: linux/amd64,linux/arm64 + # platforms: linux/amd64,linux/arm64 + platforms: linux/arm64 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=ghcr.io/${{ github.repository}}:buildcache diff --git a/Cargo.toml b/Cargo.toml index ef8024d..802000c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ cab = "0.6.0" chrono = "0.4.39" clap = { version = "4.5.27", features = ["derive"] } clap_complete = "4.5.42" -delharc = "0.6.1" +delharc = { version = "0.6.1", features = ["lh1", "lz"] } env_logger = "0.11.6" flate2 = "1.0.35" humansize = "2.1.3" diff --git a/Dockerfile b/Dockerfile index 8feceb6..aebc4d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,4 @@ -FROM rust:1-alpine3.20 AS builder - -RUN apk --no-cache add musl-dev +FROM rust:1-bookworm AS builder WORKDIR /app @@ -14,8 +12,7 @@ RUN touch src/main.rs \ && cargo build --release \ && strip target/release/totebag -o totebag -FROM gcr.io/distroless/static-debian12:nonroot -USER nonroot +FROM debian:bookworm-slim AS runner ARG VERSION=0.7.3 @@ -25,7 +22,10 @@ LABEL org.opencontainers.image.authors="Haruaki Tamada println!("archiving is done"), +//! Err(e) => eprintln!("error: {:?}", e), +//! } +//! ``` use std::collections::HashSet; use std::fs::{create_dir_all, File}; use std::path::{Path, PathBuf}; diff --git a/src/format.rs b/src/format.rs index c01fce5..9122722 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1,6 +1,36 @@ +//! Archive format management module. +//! This module provides a way to manage archive formats. +//! +//! ## Examples +//! +//! As default, [Manager] has the following formats: +//! Cab, Lha, SevenZ, Rar, Tar, TarGz, TarBz2, TarXz, TarZstd, and Zip. +//! +//! ``` +//! let manager = Manager::default(); +//! let format = manager.find(PathBuf::from("test.zip")) +//! .expect("Unexpected error: test.zip"); +//! let format_name = format.name; // should be "Zip" +//! ``` +//! +//! ## Use your own format +//! +//! ``` +//! let mut manager = Manager::default(); +//! let additional_format = ArchiveFormat::new("Compact Pro", vec![".sea", ".cpt"]); +//! manager.add(additional_format); +//! let format = manager.find("test.cpt") +//! .expect("Unexpected error: test.cpt"); +//! let format_name = format.name; // should be "Compact Pro" +//! +//! // remove the format +//! manager.remove(additional_format); +//! let _ = manager.find("test.cpt"); // should be None +//! ``` use std::fmt::Display; use std::path::Path; +/// Archive format manager. #[derive(Debug, Clone)] pub struct Manager { formats: Vec, @@ -8,26 +38,25 @@ pub struct Manager { impl Manager { pub fn default() -> Self { - Self { - formats: vec![ - ArchiveFormat::new("Cab", vec![".cab"]), - ArchiveFormat::new("Lha", vec![".lha", ".lzh"]), - ArchiveFormat::new("SevenZ", vec![".7z"]), - ArchiveFormat::new("Rar", vec![".rar"]), - ArchiveFormat::new("Tar", vec![".tar"]), - ArchiveFormat::new("TarGz", vec![".tar.gz", ".tgz"]), - ArchiveFormat::new("TarBz2", vec![".tar.bz2", ".tbz2"]), - ArchiveFormat::new("TarXz", vec![".tar.xz", ".txz"]), - ArchiveFormat::new("TarZstd", vec![".tar.zst", ".tzst", ".tar.zstd", ".tzstd"]), - ArchiveFormat::new("Zip", vec![".zip", ".jar", ".war", ".ear"]), - ], - } + Manager::new(vec![ + ArchiveFormat::new("Cab", vec![".cab"]), + ArchiveFormat::new("Lha", vec![".lha", ".lzh"]), + ArchiveFormat::new("SevenZ", vec![".7z"]), + ArchiveFormat::new("Rar", vec![".rar"]), + ArchiveFormat::new("Tar", vec![".tar"]), + ArchiveFormat::new("TarGz", vec![".tar.gz", ".tgz"]), + ArchiveFormat::new("TarBz2", vec![".tar.bz2", ".tbz2"]), + ArchiveFormat::new("TarXz", vec![".tar.xz", ".txz"]), + ArchiveFormat::new("TarZstd", vec![".tar.zst", ".tzst", ".tar.zstd", ".tzstd"]), + ArchiveFormat::new("Zip", vec![".zip", ".jar", ".war", ".ear"]), + ]) } pub fn new(formats: Vec) -> Self { Self { formats } } + /// Returns `true` if all of the given file names are Some by [method.find] method. pub fn match_all>(&self, args: &[P]) -> bool { args.iter().all(|p| self.find(p).is_some()) } @@ -35,7 +64,11 @@ impl Manager { /// Find the format of the given file name. /// If the given file name has an unknown extension for totebag, it returns an `Err(ToteErro::Unknown)`. pub fn find>(&self, path: P) -> Option<&ArchiveFormat> { - let name = path.as_ref().to_str().unwrap().to_lowercase(); + let name = path + .as_ref() + .to_str() + .expect("unexpected error: invalid path") + .to_lowercase(); for format in &self.formats { if format.is_match(&name) { return Some(&format); diff --git a/src/lib.rs b/src/lib.rs index 3e3a5ba..2c2ef9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +//! # Totebag +//! +//! `totebag` is an archiving utilities that can archive and extract files supported several formats. +//! pub mod archiver; pub mod extractor; pub mod format; @@ -11,12 +15,17 @@ pub type Result = std::result::Result; /// Define the ignore types for directory traversing. #[derive(Debug, Clone, ValueEnum, PartialEq, Copy, Hash, Eq)] pub enum IgnoreType { - /// [GitIgnore], [GitGlobal], [GitExclude], and [Ignore]. + /// [IgnoreType::GitIgnore], [IgnoreType::GitGlobal], [IgnoreType::GitExclude], and [IgnoreType::Ignore]. Default, + /// ignore hidden files and directories. Hidden, + /// ignore files and directories that are listed in `.gitignore`. GitIgnore, + /// ignore files and directories that are listed in `.gitglobal`. GitGlobal, + /// ignore files and directories that are listed in `.gitexclude`. GitExclude, + /// ignore files and directories that are listed in `.ignore`. Ignore, }