summaryrefslogtreecommitdiffstats
path: root/src/commands/release.rs
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2020-12-03 15:08:35 +0100
committerMatthias Beyer <mail@beyermatthias.de>2020-12-03 15:08:35 +0100
commit5b4617aec92fc0f7666162e3a2b8080f87f0258c (patch)
tree5f9abc885a2745b5a488cfcc0aec2e6d8d8cf0c7 /src/commands/release.rs
parent3c247e0bcd32a08668682c34b0f299af5d0606d0 (diff)
Implement release subcommand
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src/commands/release.rs')
-rw-r--r--src/commands/release.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/commands/release.rs b/src/commands/release.rs
new file mode 100644
index 0000000..4bfba2f
--- /dev/null
+++ b/src/commands/release.rs
@@ -0,0 +1,117 @@
+use std::io::Write;
+use std::path::PathBuf;
+
+use anyhow::Error;
+use anyhow::Result;
+use anyhow::anyhow;
+use clap::ArgMatches;
+use tokio::stream::StreamExt;
+use tokio::io::AsyncWriteExt;
+use diesel::prelude::*;
+
+use crate::config::*;
+use crate::package::Package;
+use crate::package::PackageName;
+use crate::package::PackageVersionConstraint;
+use crate::repository::Repository;
+use crate::source::*;
+use crate::util::progress::ProgressBars;
+use crate::db::models as dbmodels;
+use crate::schema::submits::dsl;
+use crate::config::Configuration;
+use crate::db::DbConnectionConfig;
+
+pub async fn release(db_connection_config: DbConnectionConfig, config: &Configuration, matches: &ArgMatches) -> Result<()> {
+ if !(config.releases_directory().exists() && config.releases_directory().is_dir()) {
+ return Err(anyhow!("Release directory does not exist or does not point to directory: {}", config.releases_directory().display()))
+ }
+
+ let pname = matches.value_of("package_name")
+ .map(String::from);
+
+ let pvers = matches
+ .value_of("package_version")
+ .map(String::from);
+
+ let conn = crate::db::establish_connection(db_connection_config)?;
+ let submit_uuid = matches.value_of("submit_uuid")
+ .map(uuid::Uuid::parse_str)
+ .transpose()?
+ .unwrap(); // safe by clap
+
+ let submit = crate::schema::submits::dsl::submits
+ .filter(crate::schema::submits::dsl::uuid.eq(submit_uuid))
+ .first::<dbmodels::Submit>(&conn)?;
+
+ let arts = {
+ let sel = crate::schema::artifacts::dsl::artifacts
+ .inner_join({
+ crate::schema::jobs::table
+ .inner_join(crate::schema::packages::table)
+ })
+ .filter(crate::schema::jobs::submit_id.eq(submit.id))
+ .filter(crate::schema::artifacts::released.eq(false));
+
+ match (pname, pvers) {
+ (Some(name), Some(vers)) => {
+ sel.filter(crate::schema::packages::name.eq(name))
+ .filter(crate::schema::packages::version.like(vers))
+ .load::<(dbmodels::Artifact, (dbmodels::Job, dbmodels::Package))>(&conn)?
+ },
+ (Some(name), None) => {
+ sel.filter(crate::schema::packages::name.eq(name))
+ .load::<(dbmodels::Artifact, (dbmodels::Job, dbmodels::Package))>(&conn)?
+ },
+ (None, Some(vers)) => {
+ sel.filter(crate::schema::packages::version.like(vers))
+ .load::<(dbmodels::Artifact, (dbmodels::Job, dbmodels::Package))>(&conn)?
+ },
+ (None, None) => {
+ sel.load::<(dbmodels::Artifact, (dbmodels::Job, dbmodels::Package))>(&conn)?
+ },
+ }
+ };
+
+ arts.iter()
+ .filter_map(|(art, _)| art.path_buf().parent().map(|p| config.releases_directory().join(p)))
+ .map(|p| async {
+ tokio::fs::create_dir_all(p).await.map_err(Error::from)
+ })
+ .collect::<futures::stream::FuturesUnordered<_>>()
+ .collect::<Result<()>>()
+ .await?;
+
+ let staging_base: &PathBuf = &config.staging_directory().join(submit.uuid.to_string());
+ arts.into_iter()
+ .map(|(art, _)| async move {
+ let art_path = staging_base.join(&art.path);
+ let dest_path = config.releases_directory().join(&art.path);
+ debug!("Trying to release {} to {}", art_path.display(), dest_path.display());
+
+ if !art_path.is_file() {
+ trace!("Artifact does not exist as file, cannot release it: {:?}", art);
+ Err(anyhow!("Not a file: {}", art_path.display()))
+ } else {
+ if dest_path.exists() {
+ Err(anyhow!("Does already exist: {}", dest_path.display()))
+ } else {
+ tokio::fs::rename(art_path, dest_path)
+ .await
+ .map_err(Error::from)
+ .map(|_| art)
+ }
+ }
+ })
+ .collect::<futures::stream::FuturesUnordered<_>>()
+ .collect::<Result<Vec<_>>>()
+ .await?
+ .into_iter()
+ .map(|art| {
+ diesel::update(&art)
+ .set(crate::schema::artifacts::released.eq(true))
+ .execute(&conn)
+ .map(|_| ())
+ .map_err(Error::from)
+ })
+ .collect()
+}