Feature/fix no symlink (#432)

* Refactor `BinFile::from_product`: Simplify logic flow.
* Fix `--no-symlink` behavior

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-09-28 12:32:22 +10:00 committed by GitHub
parent e3cf3e9e3a
commit c15903684f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 48 deletions

View file

@ -66,7 +66,7 @@ pub struct BinFile {
pub base_name: CompactString, pub base_name: CompactString,
pub source: PathBuf, pub source: PathBuf,
pub dest: PathBuf, pub dest: PathBuf,
pub link: PathBuf, pub link: Option<PathBuf>,
} }
impl BinFile { impl BinFile {
@ -74,6 +74,7 @@ impl BinFile {
data: &Data<'_>, data: &Data<'_>,
product: &Product, product: &Product,
bin_dir: &str, bin_dir: &str,
no_symlinks: bool,
) -> Result<Self, BinstallError> { ) -> Result<Self, BinstallError> {
let base_name = product.name.as_deref().unwrap(); let base_name = product.name.as_deref().unwrap();
@ -93,42 +94,48 @@ impl BinFile {
binary_ext, binary_ext,
}; };
// Generate install paths
// Source path is the download dir + the generated binary path
let path = ctx.render(bin_dir)?;
let path_normalized = Path::new(&path).normalize();
if path_normalized.components().next().is_none() {
return Err(BinstallError::EmptySourceFilePath);
}
if !is_valid_path(&path_normalized) {
return Err(BinstallError::InvalidSourceFilePath {
path: path_normalized.into_owned(),
});
}
let source_file_path = match path_normalized {
Cow::Borrowed(..) => path,
Cow::Owned(path) => path.to_string_lossy().into_owned(),
};
let source = if data.meta.pkg_fmt == Some(PkgFmt::Bin) { let source = if data.meta.pkg_fmt == Some(PkgFmt::Bin) {
data.bin_path.clone() data.bin_path.clone()
} else { } else {
// Generate install paths
// Source path is the download dir + the generated binary path
let path = ctx.render(bin_dir)?;
let path_normalized = Path::new(&path).normalize();
if path_normalized.components().next().is_none() {
return Err(BinstallError::EmptySourceFilePath);
}
if !is_valid_path(&path_normalized) {
return Err(BinstallError::InvalidSourceFilePath {
path: path_normalized.into_owned(),
});
}
let source_file_path = match path_normalized {
Cow::Borrowed(..) => path,
Cow::Owned(path) => path.to_string_lossy().into_owned(),
};
data.bin_path.join(&source_file_path) data.bin_path.join(&source_file_path)
}; };
// Destination path is the install dir + base-name-version{.extension} // Destination at install dir + base-name{.extension}
let dest_file_path = ctx.render("{ bin }-v{ version }{ binary-ext }")?; let dest = data
let dest = data.install_path.join(dest_file_path);
// Link at install dir + base-name{.extension}
let link = data
.install_path .install_path
.join(&ctx.render("{ bin }{ binary-ext }")?); .join(&ctx.render("{ bin }{ binary-ext }")?);
let (dest, link) = if no_symlinks {
(dest, None)
} else {
// Destination path is the install dir + base-name-version{.extension}
let dest_file_path_with_ver = ctx.render("{ bin }-v{ version }{ binary-ext }")?;
let dest_with_ver = data.install_path.join(dest_file_path_with_ver);
(dest_with_ver, Some(dest))
};
Ok(Self { Ok(Self {
base_name: CompactString::from(base_name), base_name: CompactString::from(base_name),
source, source,
@ -147,12 +154,16 @@ impl BinFile {
} }
pub fn preview_link(&self) -> String { pub fn preview_link(&self) -> String {
format!( if let Some(link) = &self.link {
"{} ({} -> {})", format!(
self.base_name, "{} ({} -> {})",
self.link.display(), self.base_name,
self.link_dest().display() link.display(),
) self.link_dest().display()
)
} else {
String::new()
}
} }
/// Return `Ok` if the source exists, otherwise `Err`. /// Return `Ok` if the source exists, otherwise `Err`.
@ -178,20 +189,22 @@ impl BinFile {
} }
pub fn install_link(&self) -> Result<(), BinstallError> { pub fn install_link(&self) -> Result<(), BinstallError> {
// Remove existing symlink if let Some(link) = &self.link {
// TODO: check if existing symlink is correct // Remove existing symlink
if self.link.exists() { // TODO: check if existing symlink is correct
debug!("Remove link '{}'", self.link.display()); if link.exists() {
std::fs::remove_file(&self.link)?; debug!("Remove link '{}'", link.display());
} std::fs::remove_file(link)?;
}
let dest = self.link_dest(); let dest = self.link_dest();
debug!( debug!(
"Create link '{}' pointing to '{}'", "Create link '{}' pointing to '{}'",
self.link.display(), link.display(),
dest.display() dest.display()
); );
atomic_symlink_file(dest, &self.link)?; atomic_symlink_file(dest, link)?;
}
Ok(()) Ok(())
} }

View file

@ -238,6 +238,7 @@ async fn resolve_inner(
&package, &package,
&install_path, &install_path,
&binaries, &binaries,
opts.no_symlinks,
) )
.await .await
{ {
@ -281,6 +282,7 @@ async fn download_extract_and_verify(
package: &Package<Meta>, package: &Package<Meta>,
install_path: &Path, install_path: &Path,
binaries: &[Product], binaries: &[Product],
no_symlinks: bool,
) -> Result<Vec<bins::BinFile>, BinstallError> { ) -> Result<Vec<bins::BinFile>, BinstallError> {
// Build final metadata // Build final metadata
let meta = fetcher.target_meta(); let meta = fetcher.target_meta();
@ -322,6 +324,7 @@ async fn download_extract_and_verify(
binaries, binaries,
bin_path.to_path_buf(), bin_path.to_path_buf(),
install_path.to_path_buf(), install_path.to_path_buf(),
no_symlinks,
)?; )?;
for bin_file in bin_files.iter() { for bin_file in bin_files.iter() {
@ -340,6 +343,7 @@ fn collect_bin_files(
binaries: &[Product], binaries: &[Product],
bin_path: PathBuf, bin_path: PathBuf,
install_path: PathBuf, install_path: PathBuf,
no_symlinks: bool,
) -> Result<Vec<bins::BinFile>, BinstallError> { ) -> Result<Vec<bins::BinFile>, BinstallError> {
// List files to be installed // List files to be installed
// based on those found via Cargo.toml // based on those found via Cargo.toml
@ -363,7 +367,7 @@ fn collect_bin_files(
// Create bin_files // Create bin_files
let bin_files = binaries let bin_files = binaries
.iter() .iter()
.map(|p| bins::BinFile::from_product(&bin_data, p, &bin_dir)) .map(|p| bins::BinFile::from_product(&bin_data, p, &bin_dir, no_symlinks))
.collect::<Result<Vec<_>, BinstallError>>()?; .collect::<Result<Vec<_>, BinstallError>>()?;
let mut source_set = BTreeSet::new(); let mut source_set = BTreeSet::new();