trim + fixes
This commit is contained in:
@ -6,6 +6,8 @@ edition='2024'
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "4.5.39"
|
clap = "4.5.39"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
|
glob = "0.3"
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
@ -14,24 +14,17 @@ musl /pkg/gnu/aeropkg/var/musl
|
|||||||
> Trimming removes unused files for a specified period
|
> Trimming removes unused files for a specified period
|
||||||
>
|
>
|
||||||
> Usage:
|
> Usage:
|
||||||
> pkg trim \<repo\> \<period\>
|
> pkg trim \<repo\> \<date\> \[time\]
|
||||||
> period relative time format:
|
> date: DD.MM.YYYY
|
||||||
> y — years, M — months, d — days, h — hours, m — minutes, s — seconds
|
> time: HH:mm:ss
|
||||||
> period absolute date format:
|
|
||||||
> DD.MM.YYYY HH:mm:ss
|
|
||||||
>
|
|
||||||
> Example:
|
|
||||||
> pkg trim musl 2d 10h
|
|
||||||
> pkg trim musl 04.09.2025 08:57:07
|
|
||||||
>
|
>
|
||||||
> Configure format
|
> Configure format
|
||||||
> Any Linux path format, relative from /pkg/\<repo\>
|
> Relative paths with /pkg/<repo>, support wildcard
|
||||||
|
> Add ! to exclude
|
||||||
|
|
||||||
``` cfg *** Trim exclude ***
|
``` cfg *** Trim rules ***
|
||||||
*
|
!**
|
||||||
```
|
!aeropkg
|
||||||
|
|
||||||
``` cfg *** Trim include ***
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|||||||
|
|
||||||
echo "Установка в '$INSTALL_PATH'..."
|
echo "Установка в '$INSTALL_PATH'..."
|
||||||
AEROPKG_HOME=$INSTALL_PATH cargo install --path . --root "$INSTALL_PATH"
|
AEROPKG_HOME=$INSTALL_PATH cargo install --path . --root "$INSTALL_PATH"
|
||||||
|
patchelf --set-interpreter /pkg/gnu/glibc/lib/ld-linux-x86-64.so.2 /pkg/gnu/aeropkg/bin/pkg
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Ошибка при установке."
|
echo "Ошибка при установке."
|
||||||
|
@ -3,6 +3,7 @@ pub mod delete;
|
|||||||
pub mod link;
|
pub mod link;
|
||||||
pub mod disable;
|
pub mod disable;
|
||||||
pub mod enable;
|
pub mod enable;
|
||||||
|
pub mod trim;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@ -10,3 +11,8 @@ use std::path::PathBuf;
|
|||||||
pub fn get_var_path() -> PathBuf {
|
pub fn get_var_path() -> PathBuf {
|
||||||
PathBuf::from(env!("AEROPKG_HOME")).join("var")
|
PathBuf::from(env!("AEROPKG_HOME")).join("var")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_etc_path() -> PathBuf {
|
||||||
|
PathBuf::from(env!("AEROPKG_HOME")).join("etc")
|
||||||
|
}
|
||||||
|
|
||||||
|
78
src/commands/trim.rs
Normal file
78
src/commands/trim.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::fs;
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
use glob::Pattern;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn trim(repo: &String, path: &Path, trim_date: i64, rules: &String) -> Result<(), std::io::Error> {
|
||||||
|
let metadata = fs::symlink_metadata(path)?;
|
||||||
|
|
||||||
|
if metadata.is_dir() {
|
||||||
|
if rules_check(repo, path, rules) {
|
||||||
|
for entry in fs::read_dir(path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let entry_path = entry.path();
|
||||||
|
trim(repo, &entry_path, trim_date, rules)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if metadata.is_file() {
|
||||||
|
if rules_check(repo, path, rules) {
|
||||||
|
let atime = metadata.atime();
|
||||||
|
if atime < trim_date {
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if metadata.file_type().is_symlink() {
|
||||||
|
if let Ok(symlink_value) = fs::read_link(path) {
|
||||||
|
let symlink_path = if symlink_value.is_relative() { path.parent().unwrap().join(&symlink_value) } else { symlink_value };
|
||||||
|
if !symlink_path.exists() {
|
||||||
|
println!("remove symlink: {} {}", path.display(), symlink_path.display());
|
||||||
|
fs::remove_file(path)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trim_handler(repo: &String, trim_date: i64) {
|
||||||
|
let etc_path = super::get_etc_path();
|
||||||
|
let cfg_path = etc_path.join("aeropkg.md");
|
||||||
|
|
||||||
|
let rules = crate::utils::parser::get_trim_rules(&cfg_path).unwrap();
|
||||||
|
|
||||||
|
let pkg_dir = PathBuf::from("/pkg").join(repo);
|
||||||
|
|
||||||
|
trim(repo, &pkg_dir, trim_date, &rules).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn rules_check(repo: &String, path: &Path, rules: &String) -> bool {
|
||||||
|
let mut confirm = true;
|
||||||
|
|
||||||
|
for rule in rules.lines() {
|
||||||
|
let mut rule = rule.trim();
|
||||||
|
|
||||||
|
let invert = rule.starts_with('!');
|
||||||
|
if invert {
|
||||||
|
rule = &rule[1..];
|
||||||
|
}
|
||||||
|
|
||||||
|
let wildcard_string = if rule.starts_with('/') {
|
||||||
|
rule.to_string()
|
||||||
|
} else {
|
||||||
|
format!("/pkg/{}/{}", repo, rule)
|
||||||
|
};
|
||||||
|
|
||||||
|
let path_str = path.to_str().unwrap_or("");
|
||||||
|
|
||||||
|
if let Ok(pattern) = Pattern::new(&wildcard_string) {
|
||||||
|
if pattern.matches(path_str) {
|
||||||
|
confirm = !invert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm
|
||||||
|
}
|
37
src/main.rs
37
src/main.rs
@ -1,5 +1,6 @@
|
|||||||
mod commands;
|
mod commands;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = clap::Command::new("pkg")
|
let matches = clap::Command::new("pkg")
|
||||||
@ -53,6 +54,28 @@ fn main() {
|
|||||||
.index(2),
|
.index(2),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
clap::Command::new("trim")
|
||||||
|
.about("Remove unused files within a specified period")
|
||||||
|
.arg(
|
||||||
|
clap::Arg::new("repo")
|
||||||
|
.help("Repository name")
|
||||||
|
.required(true)
|
||||||
|
.index(1),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::new("date")
|
||||||
|
.help("DD.MM.YYYY")
|
||||||
|
.required(true)
|
||||||
|
.index(2),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::new("time")
|
||||||
|
.help("HH:mm:ss")
|
||||||
|
.required(false)
|
||||||
|
.index(3),
|
||||||
|
),
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
clap::Command::new("disable")
|
clap::Command::new("disable")
|
||||||
.about("Disable package")
|
.about("Disable package")
|
||||||
@ -120,6 +143,20 @@ fn main() {
|
|||||||
Ok(_) => println!("link completed successfully."),
|
Ok(_) => println!("link completed successfully."),
|
||||||
Err(e) => eprintln!("Error during link: {}", e),
|
Err(e) => eprintln!("Error during link: {}", e),
|
||||||
}
|
}
|
||||||
|
} else if let Some(trim_matches) = matches.subcommand_matches("trim") {
|
||||||
|
let repo = trim_matches.get_one::<String>("repo").unwrap();
|
||||||
|
let date = trim_matches.get_one::<String>("date").unwrap();
|
||||||
|
|
||||||
|
let time = trim_matches.get_one::<String>("time").map(|s| s.as_str()).unwrap_or("00:00:00");
|
||||||
|
|
||||||
|
let datetime_str = format!("{} {}", date, time);
|
||||||
|
|
||||||
|
let datetime = NaiveDateTime::parse_from_str(&datetime_str, "%d.%m.%Y %H:%M:%S")
|
||||||
|
.expect("Invalid date or time format. Expected format: DD.MM.YYYY HH:mm:ss");
|
||||||
|
|
||||||
|
let trim_date = datetime.and_utc().timestamp();
|
||||||
|
|
||||||
|
commands::trim::trim_handler(&repo, trim_date);
|
||||||
} else if let Some(disable_matches) = matches.subcommand_matches("disable") {
|
} else if let Some(disable_matches) = matches.subcommand_matches("disable") {
|
||||||
let repo = disable_matches.get_one::<String>("repo").unwrap();
|
let repo = disable_matches.get_one::<String>("repo").unwrap();
|
||||||
let pkgname = disable_matches.get_one::<String>("pkgname").unwrap();
|
let pkgname = disable_matches.get_one::<String>("pkgname").unwrap();
|
||||||
|
0
src/utils/env.rs
Normal file
0
src/utils/env.rs
Normal file
@ -76,7 +76,7 @@ fn hardcopy(
|
|||||||
})?;
|
})?;
|
||||||
} else if metadata.file_type().is_symlink() {
|
} else if metadata.file_type().is_symlink() {
|
||||||
let symlink_value = fs::read_link(source)?;
|
let symlink_value = fs::read_link(source)?;
|
||||||
fs::remove_file(destination)?;
|
if destination.exists() { fs::remove_file(destination)? }
|
||||||
unix::fs::symlink(symlink_value, destination)?;
|
unix::fs::symlink(symlink_value, destination)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
src/utils/hooks.rs
Normal file
0
src/utils/hooks.rs
Normal file
@ -1,5 +1,4 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::env;
|
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
use std::path::{Path,PathBuf};
|
use std::path::{Path,PathBuf};
|
||||||
|
|
||||||
@ -59,10 +58,12 @@ pub fn get_patch_script<P: AsRef<Path>>(file_path: P) -> io::Result<String> {
|
|||||||
extract_block(file_path, "``` sh *** config ***", "```")
|
extract_block(file_path, "``` sh *** config ***", "```")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_trim_rules<P: AsRef<Path>>(file_path: P) -> io::Result<String> {
|
||||||
|
extract_block(file_path, "``` cfg *** Trim rules ***", "```")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_repo_list() -> io::Result<Vec<String>> {
|
pub fn get_repo_list() -> io::Result<Vec<String>> {
|
||||||
let file_path = crate::commands::get_var_path().join("aeropkg.md");
|
let file_path = crate::commands::get_etc_path().join("aeropkg.md");
|
||||||
|
|
||||||
let block = extract_block(file_path, "``` cfg *** Repository list and priority ***", "```")?;
|
let block = extract_block(file_path, "``` cfg *** Repository list and priority ***", "```")?;
|
||||||
|
|
||||||
@ -82,13 +83,9 @@ pub fn get_repo_list() -> io::Result<Vec<String>> {
|
|||||||
|
|
||||||
|
|
||||||
pub fn get_repo_addr(repo: &str) -> io::Result<String> {
|
pub fn get_repo_addr(repo: &str) -> io::Result<String> {
|
||||||
let exe_path = env::current_exe()?;
|
let file_path = crate::commands::get_etc_path().join("aeropkg.md");
|
||||||
let file_path = exe_path
|
|
||||||
.parent()
|
|
||||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to get executable directory"))?
|
|
||||||
.join("../etc/aeropkg.md");
|
|
||||||
|
|
||||||
let block = extract_block(file_path, "``` sh *** Repository list and priority ***", "```")?;
|
let block = extract_block(file_path, "``` cfg *** Repository list and priority ***", "```")?;
|
||||||
|
|
||||||
for line in block.lines() {
|
for line in block.lines() {
|
||||||
let trimmed_line = line.trim();
|
let trimmed_line = line.trim();
|
||||||
|
Reference in New Issue
Block a user