diff options
-rw-r--r-- | src/cli.rs | 18 | ||||
-rw-r--r-- | src/commands/source.rs | 55 | ||||
-rw-r--r-- | src/repository/repository.rs | 30 | ||||
-rw-r--r-- | src/source/mod.rs | 24 |
4 files changed, 103 insertions, 24 deletions
@@ -701,6 +701,24 @@ pub fn cli<'a>() -> App<'a> { .about("Overwrite existing cache entry") ) ) + .subcommand(App::new("of") + .version(crate_version!()) + .about("Get the pathes of the sources of a package") + .arg(Arg::new("package_name") + .required(false) + .multiple(false) + .index(1) + .value_name("PKG") + .about("Get the source file pathes for this package") + ) + .arg(Arg::new("package_version") + .required(false) + .multiple(false) + .index(2) + .value_name("VERSION") + .about("Get the source file pathes for the package in this version") + ) + ) ) .subcommand(App::new("release") diff --git a/src/commands/source.rs b/src/commands/source.rs index 7f4a1bb..792c036 100644 --- a/src/commands/source.rs +++ b/src/commands/source.rs @@ -42,6 +42,7 @@ pub async fn source( Some(("list-missing", matches)) => list_missing(matches, config, repo).await, Some(("url", matches)) => url(matches, repo).await, Some(("download", matches)) => download(matches, config, repo, progressbars).await, + Some(("of", matches)) => of(matches, config, repo).await, Some((other, _)) => return Err(anyhow!("Unknown subcommand: {}", other)), None => return Err(anyhow!("No subcommand")), } @@ -154,7 +155,7 @@ pub async fn list_missing(_: &ArgMatches, config: &Configuration, repo: Reposito repo.packages().try_for_each(|p| { for source in sc.sources_for(p) { - if !source.exists() { + if !source.path().exists() { writeln!( outlock, "{} {} -> {}", @@ -244,7 +245,8 @@ pub async fn download( let bar = multi.add(progressbars.spinner()); bar.set_message(&format!("Downloading {}", source.url())); async move { - if !source.exists() && source.download_manually() { + let source_path_exists = source.path().exists(); + if !source_path_exists && source.download_manually() { return Err(anyhow!( "Cannot download source that is marked for manual download" )) @@ -253,10 +255,10 @@ pub async fn download( .map_err(Error::from); } - if source.exists() && !force { + if source_path_exists && !force { Err(anyhow!("Source exists: {}", source.path().display())) } else { - if source.exists() { + if source_path_exists { let _ = source.remove_file().await?; } @@ -306,3 +308,48 @@ pub async fn download( let (r, _) = tokio::join!(r, multibar_block); r } + +async fn of( + matches: &ArgMatches, + config: &Configuration, + repo: Repository, +) -> Result<()> { + let cache = PathBuf::from(config.source_cache_root()); + let sc = SourceCache::new(cache); + let pname = matches + .value_of("package_name") + .map(String::from) + .map(PackageName::from); + let pvers = matches + .value_of("package_version") + .map(PackageVersionConstraint::try_from) + .transpose()?; + + repo.packages() + .filter(|p| pname.as_ref().map(|n| p.name() == n).unwrap_or(true)) + .filter(|p| { + pvers + .as_ref() + .map(|v| v.matches(p.version())) + .unwrap_or(true) + }) + .map(|p| { + let pathes = sc.sources_for(p) + .into_iter() + .map(|source| source.path()) + .collect::<Vec<PathBuf>>(); + + (p, pathes) + }) + .fold(Ok(std::io::stdout()), |out, (package, pathes)| { + out.and_then(|mut out| { + writeln!(out, "{} {}", package.name(), package.version())?; + for path in pathes { + writeln!(out, "\t{}", path.display())?; + } + + Ok(out) + }) + }) + .map(|_| ()) +} diff --git a/src/repository/repository.rs b/src/repository/repository.rs index e01c28f..170c2b0 100644 --- a/src/repository/repository.rs +++ b/src/repository/repository.rs @@ -18,6 +18,7 @@ use anyhow::Error; use anyhow::Result; use log::trace; use resiter::AndThen; +use resiter::FilterMap; use resiter::Map; use crate::package::Package; @@ -107,7 +108,16 @@ impl Repository { // This is either the patches array from the last recursion or the newly set one, // that doesn't matter here. let patches_before_merge = match config.get_array("patches") { - Ok(v) => v, + Ok(v) => { + v.into_iter() + .map(|p| { + p.into_str() + .map(PathBuf::from) + .with_context(|| anyhow!("patches must be strings")) + .map_err(Error::from) + }) + .collect::<Result<Vec<_>>>()? + }, Err(config::ConfigError::NotFound(_)) => vec![], Err(e) => return Err(e).map_err(Error::from), }; @@ -145,22 +155,34 @@ impl Repository { // Otherwise we have an error here, because we're refering to a non-existing file. .and_then_ok(|patch| if patch.exists() { trace!("Path to patch exists: {}", patch.display()); - Ok(config::Value::from(patch.display().to_string())) + Ok(Some(patch)) + } else if patches_before_merge.iter().any(|pb| pb.file_name() == patch.file_name()) { + // We have a patch already in the array that is named equal to the patch + // we have in the current recursion. + // It seems like this patch was already in the list and we re-found it + // because we loaded a deeper pkg.toml file. + Ok(None) } else { trace!("Path to patch does not exist: {}", patch.display()); Err(anyhow!("Patch does not exist: {}", patch.display())) }) + .filter_map_ok(|o| o) .collect::<Result<Vec<_>>>()?; // If we found any patches, use them. Otherwise use the array from before the merge // (which already has the correct pathes from the previous recursion). - let patches = if !patches.is_empty() { + let patches = if !patches.is_empty() && patches.iter().all(|p| p.exists()) { patches } else { patches_before_merge }; trace!("Patches after postprocessing merge: {:?}", patches); + let patches = patches + .into_iter() + .map(|p| p.display().to_string()) + .map(config::Value::from) + .collect::<Vec<_>>(); config.set_once("patches", config::Value::from(patches))?; } @@ -191,7 +213,7 @@ impl Repository { vec.and_then(|mut v| { trace!("Recursing into {}", dir.display()); let mut loaded = load_recursive(root, &dir, config.clone(), progress) - .with_context(|| format!("Recursing for {}", pkg_file.display()))?; + .with_context(|| format!("Reading package from {}", pkg_file.display()))?; v.append(&mut loaded); Ok(v) diff --git a/src/source/mod.rs b/src/source/mod.rs index ec0e2e2..7b84c30 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -47,14 +47,6 @@ pub struct SourceEntry { } impl SourceEntry { - fn source_file_path(&self) -> PathBuf { - self.source_file_directory().join(format!( - "{}-{}.source", - self.package_source_name, - self.package_source.hash().value() - )) - } - fn source_file_directory(&self) -> PathBuf { self.cache_root .join(format!("{}-{}", self.package_name, self.package_version)) @@ -75,12 +67,12 @@ impl SourceEntry { .collect() } - pub fn exists(&self) -> bool { - self.source_file_path().exists() - } - pub fn path(&self) -> PathBuf { - self.source_file_path() + self.source_file_directory().join(format!( + "{}-{}.source", + self.package_source_name, + self.package_source.hash().value() + )) } pub fn url(&self) -> &Url { @@ -92,13 +84,13 @@ impl SourceEntry { } pub async fn remove_file(&self) -> Result<()> { - let p = self.source_file_path(); + let p = self.path(); tokio::fs::remove_file(&p).await?; Ok(()) } pub async fn verify_hash(&self) -> Result<()> { - let p = self.source_file_path(); + let p = self.path(); trace!("Verifying : {}", p.display()); let reader = tokio::fs::OpenOptions::new() @@ -118,7 +110,7 @@ impl SourceEntry { } pub async fn create(&self) -> Result<tokio::fs::File> { - let p = self.source_file_path(); + let p = self.path(); trace!("Creating source file: {}", p.display()); if !self.cache_root.is_dir() { |