1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
use std::path::PathBuf;
use anyhow::Error;
use anyhow::Result;
use anyhow::anyhow;
use clap::ArgMatches;
use tokio::stream::StreamExt;
use diesel::prelude::*;
use crate::db::models as dbmodels;
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()
}
|