From d9bcef24533ff0a75e5514fb3f3b253e64b46c5a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 20 May 2021 12:51:57 +0100 Subject: [PATCH] otter(1) reset: Bundle uploading: Scan to see if we have to Signed-off-by: Ian Jackson --- src/bin/otter.rs | 65 ++++++++++++++++++++++++++++++++++++++++++------ src/bundles.rs | 4 +-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/bin/otter.rs b/src/bin/otter.rs index d0745dfd..76b398cd 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -729,8 +729,9 @@ mod reset_game { #[derive(Default,Debug)] struct Args { - game_spec: String, table_file: Option, + game_spec: String, + bundles: Vec, } fn subargs(sa: &mut Args) -> ArgumentParser { @@ -743,6 +744,11 @@ mod reset_game { .add_argument("GAME-SPEC",Store, "game spec, as found in server, \ or local filename if it contains a '/')"); + ap.refer(&mut sa.bundles).required() + .add_argument("BUNDLES",Collect, + "Bundle files to use. If any are specified, \ + all needed bundles must be specified, as any \ + not mentioned will be cleared from the server."); ap } @@ -778,6 +784,50 @@ mod reset_game { insns.extend(setup_table(&ma, &instance_name, &table_spec)?); } + if args.bundles.len() != 0 { + let local = args.bundles.into_iter().map(|file| { + BundleForUpload::prepare(file) + }).collect::,_>>()?; + + let resp = chan.cmd(&MgmtCommand::ListBundles { game: ma.instance() })?; + let remote = match resp { + MR::Bundles { bundles } => bundles, + x => throw!(anyhow!("unexpected response to ListBundles: {:?}",x)), + }; + + match Itertools::zip_longest( + local.iter().rev(), + remote.iter().rev(), + ).map(|eob| { + use EitherOrBoth::*; + use bundles::State::*; + match eob { + Left(local) => Err(format!("server is missing {}", local.file)), + Right(_) => Ok(()), + Both(_local, (id, Uploading)) + => Err(format!("server has incomplete upload :{}", id)), + Both(local, (id, Loaded(remote))) => { + if (local.size, local.hash) != + (remote.size, remote.hash) { + Err(format!("server's {} does not match {}", id, &local.file)) + } else { + Ok(()) + } + } + } + }).find_map(Result::err) { + None => { + eprintln!("Reusing server's existing bundles"); + }, + Some(why) => { + if ma.verbose >= 0 { + eprintln!("Re-uploading bundles: {}", why); + } + todo!(); + }, + } + } + insns.push(reset_insn); chan.alter_game(insns, None)?; @@ -1507,6 +1557,7 @@ mod alter_game_adhoc { //---------- upload-bundle ---------- struct BundleForUpload { + file: String, f: BufReader, size: usize, hash: bundles::Hash, @@ -1515,9 +1566,9 @@ struct BundleForUpload { impl BundleForUpload { #[throws(AE)] - fn prepare(file: &str) -> Self { - let f = File::open(file.clone()) - .with_context(|| file.to_owned()) + fn prepare(file: String) -> Self { + let f = File::open(&file) + .with_context(|| file.clone()) .context("open bundle file")?; let size = f .metadata().context("fstat bundle file")? @@ -1529,14 +1580,14 @@ impl BundleForUpload { let hash = bundles::Hash(hash.into()); let kind = bundles::Kind::only(); f.rewind().context("rewind bundle file")?; - BundleForUpload { f, size, hash, kind } + BundleForUpload { file, f, size, hash, kind } } #[throws(AE)] fn upload(self, ma: &MainOpts, chan: &mut MgmtChannelForGame, progress: &mut dyn termprogress::Reporter) -> bundles::Id { - let BundleForUpload { mut f, size, hash, kind } = self; + let BundleForUpload { mut f, size, hash, kind,.. } = self; let cmd = MC::UploadBundle { size, game: ma.instance(), @@ -1573,7 +1624,7 @@ mod upload_bundle { let args = parse_args::(args, &subargs, &ok_id, None); let mut chan = ma.access_game()?; let mut progress = termprogress::new(); - let for_upload = BundleForUpload::prepare(&args.bundle_file)?; + let for_upload = BundleForUpload::prepare(args.bundle_file)?; let bundle = for_upload.upload(&ma, &mut chan, &mut *progress)?; println!("{}", bundle); } diff --git a/src/bundles.rs b/src/bundles.rs index cda5f6be..1114dd9b 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -46,8 +46,8 @@ pub enum State { #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Loaded { pub meta: BundleMeta, - size: usize, - hash: bundles::Hash, + pub size: usize, + pub hash: bundles::Hash, } #[derive(Debug,Clone,Serialize,Deserialize,Default)] -- 2.30.2