Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,25 +678,25 @@
let path = path.components().collect::<Utf8PathBuf>();

// TODO: not spawn a sync environment for *every single artifact*
if let Some(mut artifact) = dep.download().await? {
if let Some(file) = tokio::task::spawn_blocking(move || {
artifact
.file(path.as_str())
.map(|mut file| {
let mut temp = tempfile::tempfile()?;
std::io::copy(&mut file, &mut temp)?;
temp.rewind()?;
Ok::<_, Report>(temp)
})
.transpose()
})
.await??
{
return Ok(Some(
ArtifactReader::from_async_file(&AsyncFile::from_std(file)).await?,
));
}
}

Check warning on line 699 in src/handler.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/handler.rs:681:5 | 681 | / if let Some(mut artifact) = dep.download().await? { 682 | | if let Some(file) = tokio::task::spawn_blocking(move || { 683 | | artifact 684 | | .file(path.as_str()) ... | 699 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 681 ~ if let Some(mut artifact) = dep.download().await? 682 ~ && let Some(file) = tokio::task::spawn_blocking(move || { 683 | artifact ... 697 | )); 698 ~ } |

Check warning on line 699 in src/handler.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/handler.rs:681:5 | 681 | / if let Some(mut artifact) = dep.download().await? { 682 | | if let Some(file) = tokio::task::spawn_blocking(move || { 683 | | artifact 684 | | .file(path.as_str()) ... | 699 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 681 ~ if let Some(mut artifact) = dep.download().await? 682 ~ && let Some(file) = tokio::task::spawn_blocking(move || { 683 | artifact ... 697 | )); 698 ~ } |

Check warning on line 699 in src/handler.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/handler.rs:681:5 | 681 | / if let Some(mut artifact) = dep.download().await? { 682 | | if let Some(file) = tokio::task::spawn_blocking(move || { 683 | | artifact 684 | | .file(path.as_str()) ... | 699 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 681 ~ if let Some(mut artifact) = dep.download().await? 682 ~ && let Some(file) = tokio::task::spawn_blocking(move || { 683 | artifact ... 697 | )); 698 ~ } |

Check warning on line 699 in src/handler.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/handler.rs:681:5 | 681 | / if let Some(mut artifact) = dep.download().await? { 682 | | if let Some(file) = tokio::task::spawn_blocking(move || { 683 | | artifact 684 | | .file(path.as_str()) ... | 699 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 681 ~ if let Some(mut artifact) = dep.download().await? 682 ~ && let Some(file) = tokio::task::spawn_blocking(move || { 683 | artifact ... 697 | )); 698 ~ } |

Ok(None)
}
Expand Down Expand Up @@ -1343,11 +1343,7 @@
.await
);

if build_info.is_branched {
dir.linkinfo.into_iter().next().unwrap().xsrcmd5
} else {
dir.srcmd5
}
dir.srcmd5
}
);

Expand Down
4 changes: 3 additions & 1 deletion src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ mod tests {
TEST_PACKAGE_2.to_owned(),
MockBranchOptions {
srcmd5: branch_srcmd5.clone(),
xsrcmd5: branch_xsrcmd5.clone(),
link_resolution: MockLinkResolution::Available {
xsrcmd5: branch_xsrcmd5.clone(),
},
..Default::default()
},
);
Expand Down
29 changes: 24 additions & 5 deletions src/prune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@

use crate::retry_request;

async fn is_originally_branched(
client: &obs::Client,
project: &str,
package: &str,
) -> Result<bool> {
// Replacing the files in a package without setting keeplink will clear the
// linkinfo, so in order to determine if this was once branched, fetch the
// very first revision and check for linkinfo there.
retry_request!(
client
.project(project.to_owned())
.package(package.to_owned())
.list(Some("1"))
.await
.wrap_err("Failed to list package @ revision 1")
)
.map(|first_rev| !first_rev.linkinfo.is_empty())
}

#[tracing::instrument(skip(client))]
pub async fn prune_branch(
client: &obs::Client,
Expand All @@ -14,6 +33,11 @@
) -> Result<()> {
// Do a sanity check to make sure this project & package are actually
// linked (i.e. we're not going to be nuking the main repository).
ensure!(
is_originally_branched(client, project, package).await?,
"Rejecting attempt to prune a non-branched package"
);

let dir = retry_request!(
client
.project(project.to_owned())
Expand All @@ -23,20 +47,15 @@
.wrap_err("Failed to list package")
)?;

ensure!(
!dir.linkinfo.is_empty(),
"Rejecting attempt to prune a non-branched package"
);

if let Some(expected_rev) = expected_rev {
if dir.rev.as_deref() != Some(expected_rev) {
info!(
"Latest revision is {}, skipping prune",
dir.rev.as_deref().unwrap_or("[unknown]")
);
return Ok(());
}
}

Check warning on line 58 in src/prune.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/prune.rs:50:5 | 50 | / if let Some(expected_rev) = expected_rev { 51 | | if dir.rev.as_deref() != Some(expected_rev) { 52 | | info!( 53 | | "Latest revision is {}, skipping prune", ... | 58 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 50 ~ if let Some(expected_rev) = expected_rev 51 ~ && dir.rev.as_deref() != Some(expected_rev) { 52 | info!( ... 56 | return Ok(()); 57 ~ } |

Check warning on line 58 in src/prune.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/prune.rs:50:5 | 50 | / if let Some(expected_rev) = expected_rev { 51 | | if dir.rev.as_deref() != Some(expected_rev) { 52 | | info!( 53 | | "Latest revision is {}, skipping prune", ... | 58 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 50 ~ if let Some(expected_rev) = expected_rev 51 ~ && dir.rev.as_deref() != Some(expected_rev) { 52 | info!( ... 56 | return Ok(()); 57 ~ } |

Check warning on line 58 in src/prune.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/prune.rs:50:5 | 50 | / if let Some(expected_rev) = expected_rev { 51 | | if dir.rev.as_deref() != Some(expected_rev) { 52 | | info!( 53 | | "Latest revision is {}, skipping prune", ... | 58 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 50 ~ if let Some(expected_rev) = expected_rev 51 ~ && dir.rev.as_deref() != Some(expected_rev) { 52 | info!( ... 56 | return Ok(()); 57 ~ } |

Check warning on line 58 in src/prune.rs

View workflow job for this annotation

GitHub Actions / cargo clippy latest

this `if` statement can be collapsed

warning: this `if` statement can be collapsed --> src/prune.rs:50:5 | 50 | / if let Some(expected_rev) = expected_rev { 51 | | if dir.rev.as_deref() != Some(expected_rev) { 52 | | info!( 53 | | "Latest revision is {}, skipping prune", ... | 58 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if help: collapse nested if block | 50 ~ if let Some(expected_rev) = expected_rev 51 ~ && dir.rev.as_deref() != Some(expected_rev) { 52 | info!( ... 56 | return Ok(()); 57 ~ } |

retry_request!(
client
Expand Down
116 changes: 27 additions & 89 deletions src/upload.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;

use bytes::Bytes;
use camino::{Utf8Path, Utf8PathBuf};
use color_eyre::eyre::{Context, Result, ensure, eyre};
use derivative::*;
use futures_util::{Stream, TryStreamExt};
use gitlab_runner::outputln;
use md5::{Digest, Md5};
use open_build_service_api as obs;
Expand All @@ -20,19 +18,6 @@ type Md5String = String;

const META_NAME: &str = "_meta";

async fn collect_byte_stream<E: std::error::Error + Send + Sync + 'static>(
stream: impl Stream<Item = Result<Bytes, E>>,
) -> Result<Vec<u8>> {
let mut data = vec![];
stream
.try_for_each(|chunk| {
data.extend_from_slice(&chunk);
futures_util::future::ready(Ok(()))
})
.await?;
Ok(data)
}

pub fn compute_md5(data: &[u8]) -> String {
base16ct::lower::encode_string(&Md5::digest(data))
}
Expand Down Expand Up @@ -168,42 +153,6 @@ impl ObsDscUploader {
}
}

#[instrument(skip(self))]
async fn find_files_to_remove(
&self,
files: &HashMap<String, Md5String>,
) -> Result<HashSet<Md5String>> {
let mut to_remove = HashSet::new();

for file in files.keys() {
if file.ends_with(".dsc") {
to_remove.insert(file.clone());

let contents = retry_request!(
collect_byte_stream(
self.client
.project(self.project.clone())
.package(self.package.clone())
.source_file(file)
.await?,
)
.instrument(info_span!("find_files_to_remove:download", %file))
.await
)?;

let _span = info_span!("find_files_to_remove:parse", %file);
let dsc: Dsc =
rfc822_like::from_str(discard_pgp(std::str::from_utf8(&contents[..])?))?;

to_remove.extend(dsc.files.into_iter().map(|f| f.filename));
} else if file.ends_with(".changes") {
to_remove.insert(file.clone());
}
}

Ok(to_remove)
}

#[instrument(skip(self))]
async fn get_latest_meta_md5(&self) -> Result<Md5String> {
let dir = retry_request!(
Expand Down Expand Up @@ -321,11 +270,7 @@ impl ObsDscUploader {
let present_files: HashMap<_, _> =
dir.entries.into_iter().map(|e| (e.name, e.md5)).collect();

let mut files_to_commit = present_files.clone();

for to_remove in self.find_files_to_remove(&files_to_commit).await? {
files_to_commit.remove(&to_remove);
}
let mut files_to_commit = HashMap::new();

for file in &self.dsc.files {
files_to_commit.insert(file.filename.clone(), file.hash.clone());
Expand Down Expand Up @@ -366,15 +311,14 @@ impl ObsDscUploader {
.await
})?;

let build_srcmd5 = if let Some(link) = current_dir.linkinfo.into_iter().next() {
link.xsrcmd5
} else {
current_dir.srcmd5
};
ensure!(
current_dir.linkinfo.is_empty(),
"linkinfo unexpectedly present after upload"
);

Ok(UploadResult {
rev,
build_srcmd5,
build_srcmd5: current_dir.srcmd5,
unchanged,
})
}
Expand Down Expand Up @@ -758,17 +702,15 @@ d29ybGQgaGVsbG8K

let mut dir = assert_ok!(package_1.list(None).await);
assert_eq!(dir.rev.as_deref(), Some("3"));
assert_eq!(dir.entries.len(), 5);
assert_eq!(dir.entries.len(), 4);
dir.entries.sort_by(|a, b| a.name.cmp(&b.name));
assert_eq!(dir.entries[0].name, "_meta");
assert_eq!(dir.entries[1].name, already_present_file);
assert_eq!(dir.entries[1].md5, already_present_md5);
assert_eq!(dir.entries[2].name, dsc2_file.file_name().unwrap());
assert_eq!(dir.entries[2].md5, dsc2_md5);
assert_eq!(dir.entries[3].name, test1_file);
assert_eq!(dir.entries[3].md5, test1_md5_a);
assert_eq!(dir.entries[4].name, test2_file);
assert_eq!(dir.entries[4].md5, test2_md5);
assert_eq!(dir.entries[1].name, dsc2_file.file_name().unwrap());
assert_eq!(dir.entries[1].md5, dsc2_md5);
assert_eq!(dir.entries[2].name, test1_file);
assert_eq!(dir.entries[2].md5, test1_md5_a);
assert_eq!(dir.entries[3].name, test2_file);
assert_eq!(dir.entries[3].md5, test2_md5);

assert_eq!(dir.srcmd5, result.build_srcmd5);

Expand All @@ -794,17 +736,15 @@ d29ybGQgaGVsbG8K

let mut dir = assert_ok!(package_1.list(None).await);
assert_eq!(dir.rev.as_deref(), Some("4"));
assert_eq!(dir.entries.len(), 5);
assert_eq!(dir.entries.len(), 4);
dir.entries.sort_by(|a, b| a.name.cmp(&b.name));
assert_eq!(dir.entries[0].name, "_meta");
assert_eq!(dir.entries[1].name, already_present_file);
assert_eq!(dir.entries[1].md5, already_present_md5);
assert_eq!(dir.entries[2].name, dsc3_file.file_name().unwrap());
assert_eq!(dir.entries[2].md5, dsc3_md5);
assert_eq!(dir.entries[3].name, test1_file);
assert_eq!(dir.entries[3].md5, test1_md5_b);
assert_eq!(dir.entries[4].name, test2_file);
assert_eq!(dir.entries[4].md5, test2_md5);
assert_eq!(dir.entries[1].name, dsc3_file.file_name().unwrap());
assert_eq!(dir.entries[1].md5, dsc3_md5);
assert_eq!(dir.entries[2].name, test1_file);
assert_eq!(dir.entries[2].md5, test1_md5_b);
assert_eq!(dir.entries[3].name, test2_file);
assert_eq!(dir.entries[3].md5, test2_md5);

assert_eq!(dir.srcmd5, result.build_srcmd5);

Expand All @@ -826,15 +766,13 @@ d29ybGQgaGVsbG8K

let mut dir = assert_ok!(package_1.list(None).await);
assert_eq!(dir.rev.as_deref(), Some("5"));
assert_eq!(dir.entries.len(), 4);
assert_eq!(dir.entries.len(), 3);
dir.entries.sort_by(|a, b| a.name.cmp(&b.name));
assert_eq!(dir.entries[0].name, "_meta");
assert_eq!(dir.entries[1].name, already_present_file);
assert_eq!(dir.entries[1].md5, already_present_md5);
assert_eq!(dir.entries[2].name, dsc4_file.file_name().unwrap());
assert_eq!(dir.entries[2].md5, dsc4_md5);
assert_eq!(dir.entries[3].name, test1_file);
assert_eq!(dir.entries[3].md5, test1_md5_b);
assert_eq!(dir.entries[1].name, dsc4_file.file_name().unwrap());
assert_eq!(dir.entries[1].md5, dsc4_md5);
assert_eq!(dir.entries[2].name, test1_file);
assert_eq!(dir.entries[2].md5, test1_md5_b);

// Re-upload with no changes and ensure the old commit is returned.

Expand Down Expand Up @@ -873,6 +811,6 @@ d29ybGQgaGVsbG8K
// XXX: the mock apis don't set the correct rev values on branch yet
assert_matches!(dir.rev, Some(_));

assert_eq!(dir.linkinfo[0].xsrcmd5, result.build_srcmd5);
assert!(dir.linkinfo.is_empty());
}
}
Loading