Skip to content
Merged
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
42 changes: 23 additions & 19 deletions src/admin/default_versions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::models::{update_default_version, verify_default_version};
use crate::tasks::spawn_blocking;
use crate::{db, schema::crates};
use anyhow::Context;
use diesel::prelude::*;
Expand All @@ -14,29 +15,32 @@
Verify,
}

pub fn run(command: Command) -> anyhow::Result<()> {
let mut conn = db::oneoff_connection().context("Failed to connect to the database")?;
pub async fn run(command: Command) -> anyhow::Result<()> {
spawn_blocking(move || {
let mut conn = db::oneoff_connection().context("Failed to connect to the database")?;

Check warning on line 20 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L18-L20

Added lines #L18 - L20 were not covered by tests

let crate_ids: Vec<i32> = crates::table
.select(crates::id)
.load(&mut conn)
.context("Failed to load crates")?;
let crate_ids: Vec<i32> = crates::table
.select(crates::id)
.load(&mut conn)
.context("Failed to load crates")?;

Check warning on line 25 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L22-L25

Added lines #L22 - L25 were not covered by tests

let pb = ProgressBar::new(crate_ids.len() as u64);
pb.set_style(ProgressStyle::with_template(
"{bar:60} ({pos}/{len}, ETA {eta})",
)?);
let pb = ProgressBar::new(crate_ids.len() as u64);
pb.set_style(ProgressStyle::with_template(
"{bar:60} ({pos}/{len}, ETA {eta})",
)?);

Check warning on line 30 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L27-L30

Added lines #L27 - L30 were not covered by tests

for crate_id in crate_ids.into_iter().progress_with(pb.clone()) {
let func = match command {
Command::Update => update_default_version,
Command::Verify => verify_default_version,
};
for crate_id in crate_ids.into_iter().progress_with(pb.clone()) {
let func = match command {
Command::Update => update_default_version,
Command::Verify => verify_default_version,

Check warning on line 35 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L32-L35

Added lines #L32 - L35 were not covered by tests
};

if let Err(error) = func(crate_id, &mut conn) {
pb.suspend(|| warn!(%crate_id, %error, "Failed to update the default version"));
if let Err(error) = func(crate_id, &mut conn) {
pb.suspend(|| warn!(%crate_id, %error, "Failed to update the default version"));
}

Check warning on line 40 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L38-L40

Added lines #L38 - L40 were not covered by tests
}
}

Ok(())
Ok(())
})
.await

Check warning on line 45 in src/admin/default_versions.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/default_versions.rs#L43-L45

Added lines #L43 - L45 were not covered by tests
}
93 changes: 49 additions & 44 deletions src/admin/delete_crate.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::schema::{crate_owners, teams, users};
use crate::tasks::spawn_blocking;
use crate::worker::jobs;
use crate::{admin::dialoguer, db, schema::crates};
use anyhow::Context;
Expand All @@ -24,13 +25,15 @@
yes: bool,
}

pub fn run(opts: Opts) -> anyhow::Result<()> {
let conn = &mut db::oneoff_connection().context("Failed to establish database connection")?;
pub async fn run(opts: Opts) -> anyhow::Result<()> {
spawn_blocking(move || {
let conn =
&mut db::oneoff_connection().context("Failed to establish database connection")?;

Check warning on line 31 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L28-L31

Added lines #L28 - L31 were not covered by tests

let mut crate_names = opts.crate_names;
crate_names.sort();
let mut crate_names = opts.crate_names;
crate_names.sort();

Check warning on line 34 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L33-L34

Added lines #L33 - L34 were not covered by tests

let query_result = crates::table
let query_result = crates::table

Check warning on line 36 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L36

Added line #L36 was not covered by tests
.select((
crates::name,
crates::id,
Expand All @@ -45,53 +48,55 @@
.load::<(String, i32, String)>(conn)
.context("Failed to look up crate name from the database")?;

let mut existing_crates: HashMap<String, (i32, Vec<String>)> = HashMap::new();
for (name, id, login) in query_result {
let entry = existing_crates
.entry(name)
.or_insert_with(|| (id, Vec::new()));
let mut existing_crates: HashMap<String, (i32, Vec<String>)> = HashMap::new();
for (name, id, login) in query_result {
let entry = existing_crates
.entry(name)
.or_insert_with(|| (id, Vec::new()));

Check warning on line 55 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L51-L55

Added lines #L51 - L55 were not covered by tests

entry.1.push(login);
}
entry.1.push(login);
}

Check warning on line 58 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L57-L58

Added lines #L57 - L58 were not covered by tests

println!("Deleting the following crates:");
println!();
for name in &crate_names {
match existing_crates.get(name) {
Some((id, owners)) => {
let owners = owners.join(", ");
println!(" - {name} (id={id}, owners={owners})");
println!("Deleting the following crates:");
println!();
for name in &crate_names {
match existing_crates.get(name) {
Some((id, owners)) => {
let owners = owners.join(", ");
println!(" - {name} (id={id}, owners={owners})");
}
None => println!(" - {name} (⚠️ crate not found)"),

Check warning on line 68 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L60-L68

Added lines #L60 - L68 were not covered by tests
}
None => println!(" - {name} (⚠️ crate not found)"),
}
}
println!();
println!();

Check warning on line 71 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L71

Added line #L71 was not covered by tests

if !opts.yes && !dialoguer::confirm("Do you want to permanently delete these crates?") {
return Ok(());
}
if !opts.yes && !dialoguer::confirm("Do you want to permanently delete these crates?") {
return Ok(());
}

Check warning on line 75 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L73-L75

Added lines #L73 - L75 were not covered by tests

for name in &crate_names {
if let Some((id, _)) = existing_crates.get(name) {
info!("{name}: Deleting crate from the database…");
if let Err(error) = diesel::delete(crates::table.find(id)).execute(conn) {
warn!(%id, "{name}: Failed to delete crate from the database: {error}");
}
} else {
info!("{name}: Skipped missing crate");
};
for name in &crate_names {
if let Some((id, _)) = existing_crates.get(name) {
info!("{name}: Deleting crate from the database…");
if let Err(error) = diesel::delete(crates::table.find(id)).execute(conn) {
warn!(%id, "{name}: Failed to delete crate from the database: {error}");
}

Check warning on line 82 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L77-L82

Added lines #L77 - L82 were not covered by tests
} else {
info!("{name}: Skipped missing crate");

Check warning on line 84 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L84

Added line #L84 was not covered by tests
};

info!("{name}: Enqueuing index sync jobs…");
if let Err(error) = jobs::enqueue_sync_to_index(name, conn) {
warn!("{name}: Failed to enqueue index sync jobs: {error}");
}
info!("{name}: Enqueuing index sync jobs…");
if let Err(error) = jobs::enqueue_sync_to_index(name, conn) {
warn!("{name}: Failed to enqueue index sync jobs: {error}");
}

Check warning on line 90 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L87-L90

Added lines #L87 - L90 were not covered by tests

info!("{name}: Enqueuing DeleteCrateFromStorage job…");
let job = jobs::DeleteCrateFromStorage::new(name.into());
if let Err(error) = job.enqueue(conn) {
warn!("{name}: Failed to enqueue DeleteCrateFromStorage job: {error}");
info!("{name}: Enqueuing DeleteCrateFromStorage job…");
let job = jobs::DeleteCrateFromStorage::new(name.into());
if let Err(error) = job.enqueue(conn) {
warn!("{name}: Failed to enqueue DeleteCrateFromStorage job: {error}");
}

Check warning on line 96 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L92-L96

Added lines #L92 - L96 were not covered by tests
}
}

Ok(())
Ok(())
})
.await

Check warning on line 101 in src/admin/delete_crate.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_crate.rs#L99-L101

Added lines #L99 - L101 were not covered by tests
}
143 changes: 73 additions & 70 deletions src/admin/delete_version.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::models::update_default_version;
use crate::schema::crates;
use crate::storage::Storage;
use crate::tasks::spawn_blocking;
use crate::worker::jobs;
use crate::{admin::dialoguer, db, schema::versions};
use anyhow::Context;
Expand All @@ -25,86 +26,88 @@
yes: bool,
}

pub fn run(opts: Opts) -> anyhow::Result<()> {
let crate_name = &opts.crate_name;

let conn = &mut db::oneoff_connection().context("Failed to establish database connection")?;

let store = Storage::from_environment();

let crate_id: i32 = crates::table
.select(crates::id)
.filter(crates::name.eq(crate_name))
.first(conn)
.context("Failed to look up crate id from the database")?;

println!("Deleting the following versions of the `{crate_name}` crate:");
println!();
for version in &opts.versions {
println!(" - {version}");
}
println!();

if !opts.yes && !dialoguer::confirm("Do you want to permanently delete these versions?") {
return Ok(());
}

conn.transaction(|conn| {
info!(%crate_name, %crate_id, versions = ?opts.versions, "Deleting versions from the database");
let result = diesel::delete(
versions::table
.filter(versions::crate_id.eq(crate_id))
.filter(versions::num.eq_any(&opts.versions)),
)
.execute(conn);

match result {
Ok(num_deleted) if num_deleted == opts.versions.len() => {}
Ok(num_deleted) => {
warn!(
%crate_name,
"Deleted only {num_deleted} of {num_expected} versions from the database",
num_expected = opts.versions.len()
);
}
Err(error) => {
warn!(%crate_name, ?error, "Failed to delete versions from the database")
}
pub async fn run(opts: Opts) -> anyhow::Result<()> {
spawn_blocking(move || {
let crate_name = &opts.crate_name;

Check warning on line 31 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L29-L31

Added lines #L29 - L31 were not covered by tests

let conn = &mut db::oneoff_connection().context("Failed to establish database connection")?;

Check warning on line 33 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L33

Added line #L33 was not covered by tests

let store = Storage::from_environment();

Check warning on line 35 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L35

Added line #L35 was not covered by tests

let crate_id: i32 = crates::table
.select(crates::id)
.filter(crates::name.eq(crate_name))
.first(conn)
.context("Failed to look up crate id from the database")?;

Check warning on line 41 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L37-L41

Added lines #L37 - L41 were not covered by tests

println!("Deleting the following versions of the `{crate_name}` crate:");
println!();
for version in &opts.versions {
println!(" - {version}");

Check warning on line 46 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L43-L46

Added lines #L43 - L46 were not covered by tests
}
println!();

Check warning on line 48 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L48

Added line #L48 was not covered by tests

info!(%crate_name, %crate_id, "Updating default version in the database");
if let Err(error) = update_default_version(crate_id, conn) {
warn!(%crate_name, %crate_id, ?error, "Failed to update default version");
if !opts.yes && !dialoguer::confirm("Do you want to permanently delete these versions?") {
return Ok(());

Check warning on line 51 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L50-L51

Added lines #L50 - L51 were not covered by tests
}

Ok::<_, anyhow::Error>(())
})?;
conn.transaction(|conn| {
info!(%crate_name, %crate_id, versions = ?opts.versions, "Deleting versions from the database");
let result = diesel::delete(
versions::table
.filter(versions::crate_id.eq(crate_id))
.filter(versions::num.eq_any(&opts.versions)),
)
.execute(conn);

Check warning on line 61 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L54-L61

Added lines #L54 - L61 were not covered by tests

match result {
Ok(num_deleted) if num_deleted == opts.versions.len() => {}
Ok(num_deleted) => {
warn!(

Check warning on line 66 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L63-L66

Added lines #L63 - L66 were not covered by tests
%crate_name,
"Deleted only {num_deleted} of {num_expected} versions from the database",
num_expected = opts.versions.len()

Check warning on line 69 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L68-L69

Added lines #L68 - L69 were not covered by tests
);
}
Err(error) => {
warn!(%crate_name, ?error, "Failed to delete versions from the database")

Check warning on line 73 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L72-L73

Added lines #L72 - L73 were not covered by tests
}
}

info!(%crate_name, "Enqueuing index sync jobs");
if let Err(error) = jobs::enqueue_sync_to_index(crate_name, conn) {
warn!(%crate_name, ?error, "Failed to enqueue index sync jobs");
}
info!(%crate_name, %crate_id, "Updating default version in the database");
if let Err(error) = update_default_version(crate_id, conn) {
warn!(%crate_name, %crate_id, ?error, "Failed to update default version");
}

Check warning on line 80 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L77-L80

Added lines #L77 - L80 were not covered by tests

let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.context("Failed to initialize tokio runtime")?;
Ok::<_, anyhow::Error>(())
})?;

Check warning on line 83 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L82-L83

Added lines #L82 - L83 were not covered by tests

for version in &opts.versions {
debug!(%crate_name, %version, "Deleting crate file from S3");
if let Err(error) = rt.block_on(store.delete_crate_file(crate_name, version)) {
warn!(%crate_name, %version, ?error, "Failed to delete crate file from S3");
info!(%crate_name, "Enqueuing index sync jobs");
if let Err(error) = jobs::enqueue_sync_to_index(crate_name, conn) {
warn!(%crate_name, ?error, "Failed to enqueue index sync jobs");

Check warning on line 87 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L85-L87

Added lines #L85 - L87 were not covered by tests
}

debug!(%crate_name, %version, "Deleting readme file from S3");
match rt.block_on(store.delete_readme(crate_name, version)) {
Err(object_store::Error::NotFound { .. }) => {}
Err(error) => {
warn!(%crate_name, %version, ?error, "Failed to delete readme file from S3")
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.context("Failed to initialize tokio runtime")?;

Check warning on line 93 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L90-L93

Added lines #L90 - L93 were not covered by tests

for version in &opts.versions {
debug!(%crate_name, %version, "Deleting crate file from S3");
if let Err(error) = rt.block_on(store.delete_crate_file(crate_name, version)) {
warn!(%crate_name, %version, ?error, "Failed to delete crate file from S3");
}

Check warning on line 99 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L95-L99

Added lines #L95 - L99 were not covered by tests

debug!(%crate_name, %version, "Deleting readme file from S3");
match rt.block_on(store.delete_readme(crate_name, version)) {
Err(object_store::Error::NotFound { .. }) => {}
Err(error) => {
warn!(%crate_name, %version, ?error, "Failed to delete readme file from S3")

Check warning on line 105 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L101-L105

Added lines #L101 - L105 were not covered by tests
}
Ok(_) => {}

Check warning on line 107 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L107

Added line #L107 was not covered by tests
}
Ok(_) => {}
}
}

Ok(())
Ok(())
}).await

Check warning on line 112 in src/admin/delete_version.rs

View check run for this annotation

Codecov / codecov/patch

src/admin/delete_version.rs#L111-L112

Added lines #L111 - L112 were not covered by tests
}
Loading