feat: add global lock

Signed-off-by: sisungo <[email protected]>
This commit is contained in:
2026-07-09 01:54:25 +08:00
parent 459074237f
commit 1c154e7675
6 changed files with 134 additions and 7 deletions
+58 -6
View File
@@ -1,7 +1,11 @@
use crate::common::format_size;
use anyhow::anyhow;
use clap::Parser;
use packie::{PackieBuilder, package::PkgSpec};
use packie::{
PackieBuilder,
local::Installation,
package::{PkgManifest, PkgSpec},
};
use rust_i18n::t;
#[derive(Debug, Parser)]
@@ -20,11 +24,59 @@ pub fn main(cli: Cli) -> anyhow::Result<()> {
}
let found = found.remove(0);
println!("Package name: {}", found.pkg_manifest.name);
println!("Package version: {}", found.pkg_manifest.version);
println!("Package architecture: {}", found.pkg_manifest.arch);
println!("Install package spec: {}", found.install_pkgspec);
println!("Installed size: {}", format_size(found.installed_size));
print_pkgmanifest(&found.pkg_manifest);
print_install_misc(&found);
Ok(())
}
fn print_pkgmanifest(pkg_manifest: &PkgManifest) {
println!(
"{}: {}",
t!("info.print_pkgmanifest.name"),
pkg_manifest.name
);
println!(
"{}: {}",
t!("info.print_pkgmanifest.version"),
pkg_manifest.version
);
println!(
"{}: {}",
t!("info.print_pkgmanifest.arch"),
pkg_manifest.arch
);
if !pkg_manifest.description.is_empty() {
println!(
"{}: {}",
t!("info.print_pkgmanifest.description"),
pkg_manifest.arch
);
}
println!("{}:", t!("info.print_pkgmanifest.dependencies"));
for i in pkg_manifest.dependencies.iter() {
println!(" - {i}");
}
println!("{}:", t!("info.print_pkgmanifest.recommendations"));
for i in pkg_manifest.recommendations.iter() {
println!(" - {i}");
}
}
fn print_install_misc(installation: &Installation) {
println!(
"{}: {}",
t!("info.print_install_misc.install_pkgspec"),
installation.install_pkgspec
);
println!(
"{}: {}",
t!("info.print_install_misc.install_date"),
installation.install_date,
);
println!(
"{}: {}",
t!("info.print_install_misc.installed_size"),
format_size(installation.installed_size),
);
}
+3
View File
@@ -41,3 +41,6 @@ repo.RepoError.AllTriesFailed:
repo.download.DownloadError.Checksum:
en: "checksum failed"
zh-CN: "文件完整性检查失败"
BuildPackieError.Lock:
en: "failed to lock packie database: %{error}"
zh-CN: "无法锁定 Packie 数据库:%{error}"
+27
View File
@@ -23,6 +23,33 @@ info.no_package_found:
info.pkgspec_not_unique:
en: "The specified package spec was not unique."
zh-CN: "指定的包规范匹配了多个包。"
info.print_pkgmanifest.name:
en: "Package name"
zh-CN: "包名"
info.print_pkgmanifest.version:
en: "Package version"
zh-CN: "版本"
info.print_pkgmanifest.arch:
en: "Package architecture"
zh-CN: "架构"
info.print_pkgmanifest.dependencies:
en: "Dependencies"
zh-CN: "依赖"
info.print_pkgmanifest.recommendations:
en: "Recommendations"
zh-CN: "建议安装"
info.print_pkgmanifest.description:
en: "Description"
zh-CN: "描述"
info.print_install_misc.install_pkgspec:
en: "Install package spec"
zh-CN: "安装请求"
info.print_install_misc.installed_size:
en: "Installed size"
zh-CN: "安装后大小"
info.print_install_misc.install_date:
en: "Install date"
zh-CN: "安装日期"
remove.package_not_found:
en: "The specified package was not found."
zh-CN: "找不到指定的包。"
+21
View File
@@ -160,3 +160,24 @@ pub struct CopyError {
dst: PathBuf,
error: std::io::Error,
}
#[cfg(target_family = "unix")]
#[derive(Debug)]
pub struct LockGuard(Option<nix::fcntl::Flock<std::fs::File>>);
#[cfg(target_family = "unix")]
impl LockGuard {
pub fn noop() -> Self {
Self(None)
}
pub fn open(path: impl AsRef<Path>, nonblocking: bool) -> std::io::Result<Self> {
let file = std::fs::File::options().create(true).open(path)?;
let flags = if nonblocking {
nix::fcntl::FlockArg::LockExclusiveNonblock
} else {
nix::fcntl::FlockArg::LockExclusive
};
let lock = nix::fcntl::Flock::lock(file, flags).map_err(|x| x.1)?;
Ok(Self(Some(lock)))
}
}
+21 -1
View File
@@ -9,9 +9,11 @@ pub mod remove;
pub mod repo;
pub mod version;
use common::fs::LockGuard;
use config::AllConfig;
use local::{Cache, DataDir, LocalDb};
use profile::Profile;
use rust_i18n::t;
rust_i18n::i18n!("locales/libpackie", fallback = "en");
@@ -23,6 +25,7 @@ pub struct Packie {
config: AllConfig,
local_data: DataDir,
cache: Cache,
_lock_guard: LockGuard,
}
impl Packie {
/// Returns profile of the Packie instance.
@@ -31,16 +34,18 @@ impl Packie {
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct PackieBuilder {
profile: Profile,
readonly: bool,
nonblocking: bool,
}
impl PackieBuilder {
pub fn new() -> Self {
Self {
profile: Profile::builtin(),
readonly: false,
nonblocking: false,
}
}
@@ -49,17 +54,27 @@ impl PackieBuilder {
self
}
pub fn nonblocking(mut self, val: bool) -> Self {
self.nonblocking = val;
self
}
pub fn profile(mut self, val: Profile) -> Self {
self.profile = val;
self
}
pub fn build(self) -> Result<Packie, BuildPackieError> {
let mut _lock_guard = LockGuard::noop();
if !self.readonly {
_ = std::fs::create_dir_all(&self.profile.packie_data_dir);
_ = std::fs::create_dir_all(&self.profile.packie_cache_dir);
_ = std::fs::create_dir_all(&self.profile.packie_config_dir);
_ = std::fs::create_dir_all(&self.profile.pkg_dir);
let lock_path = self.profile.packie_data_dir.join("packie.lock");
_lock_guard =
LockGuard::open(lock_path, self.nonblocking).map_err(BuildPackieError::Lock)?;
}
let local_db_path = self.profile.packie_data_dir.join(LocalDb::FILENAME);
let open_local_db = if self.readonly {
@@ -71,12 +86,14 @@ impl PackieBuilder {
let config = AllConfig::open(&self.profile.packie_config_dir);
let cache = Cache(self.profile.packie_cache_dir.clone());
let local_data = DataDir(self.profile.packie_data_dir.clone());
Ok(Packie {
profile: self.profile,
local_db,
config,
cache,
local_data,
_lock_guard,
})
}
}
@@ -85,4 +102,7 @@ impl PackieBuilder {
pub enum BuildPackieError {
#[error("{0}")]
LocalDb(rusqlite::Error),
#[error("{}", t!("BuildPackieError.Lock", error = .0))]
Lock(std::io::Error),
}
+4
View File
@@ -92,6 +92,10 @@ pub struct PkgManifest {
#[serde(default)]
pub dependencies: Vec<PkgSpec>,
/// Package recommended (soft) dependencies.
#[serde(default)]
pub recommendations: Vec<PkgSpec>,
/// Provided abstract packages.
#[serde(default)]
pub provides: Vec<AbsPkgIdent>,