From 4e665b621415f7baa22e589161afd82f971b4828 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Sat, 13 Mar 2021 13:33:27 -0800 Subject: [PATCH] Run the one-step importer from the UI. Don't attempt a proper loading screen yet. #523 Not working yet; one_step assumes paths to binaries, and it's now wrong. --- importer/src/bin/one_step_import.rs | 21 ++++-- map_gui/src/tools/importer.rs | 100 ++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 20 deletions(-) diff --git a/importer/src/bin/one_step_import.rs b/importer/src/bin/one_step_import.rs index fa65ee60cc..ad779d8ea8 100644 --- a/importer/src/bin/one_step_import.rs +++ b/importer/src/bin/one_step_import.rs @@ -11,6 +11,7 @@ use abstutil::{must_run_cmd, CmdArgs}; fn main() -> Result<()> { let mut args = CmdArgs::new(); let geojson_path = args.required_free(); + let drive_on_left = args.enabled("--drive_on_left"); args.done(); // TODO Assumes the binaries are in hardcoded target directories... we could be smarter and @@ -18,6 +19,7 @@ fn main() -> Result<()> { // Convert to a boundary polygon. This tool reads from STDIN. { + println!("Converting GeoJSON to Osmosis boundary"); let geojson = abstio::slurp_file(geojson_path)?; let mut cmd = Command::new("./target/debug/geojson_to_osmosis") .stdin(Stdio::piped()) @@ -29,17 +31,18 @@ fn main() -> Result<()> { // What file should we download? let url = { + println!("Figuring out what Geofabrik file contains your boundary"); let out = Command::new("./target/debug/pick_geofabrik") .arg("boundary0.poly") .output()?; assert!(out.status.success()); String::from_utf8(out.stdout)? }; - println!("go dl {}", url); // Download it! // TODO This is timing out. Also, really could use progress bars. { + println!("Downloading {}", url); let resp = reqwest::blocking::get(&url)?; assert!(resp.status().is_success()); let bytes = resp.bytes()?; @@ -48,6 +51,7 @@ fn main() -> Result<()> { } // Clip it + println!("Clipping osm.pbf file to your boundary"); must_run_cmd( Command::new("./target/release/clip_osm") .arg("--pbf=raw.pbf") @@ -56,11 +60,16 @@ fn main() -> Result<()> { ); // Import! - must_run_cmd( - Command::new("./target/release/importer") - .arg("--oneshot=clipped.osm") - .arg("--oneshot_clip=boundary0.poly"), - ); + { + let mut cmd = Command::new("./target/release/importer"); + cmd.arg("--oneshot=clipped.osm"); + cmd.arg("--oneshot_clip=boundary0.poly"); + if drive_on_left { + cmd.arg("--oneshot_drive_on_left"); + } + println!("Running importer"); + must_run_cmd(&mut cmd); + } Ok(()) } diff --git a/map_gui/src/tools/importer.rs b/map_gui/src/tools/importer.rs index 4719620a14..f62155a871 100644 --- a/map_gui/src/tools/importer.rs +++ b/map_gui/src/tools/importer.rs @@ -1,9 +1,12 @@ use std::io::Write; +use std::process::Command; use anyhow::Result; use clipboard::{ClipboardContext, ClipboardProvider}; -use widgetry::{EventCtx, Line, Panel, SimpleState, State, TextExt, Toggle, Transition, Widget}; +use widgetry::{ + EventCtx, GfxCtx, Line, Panel, SimpleState, State, Text, TextExt, Toggle, Transition, Widget, +}; use crate::tools::{open_browser, PopupMsg}; use crate::AppLike; @@ -55,7 +58,13 @@ impl ImportCity { } impl SimpleState for ImportCity { - fn on_click(&mut self, ctx: &mut EventCtx, _: &mut A, x: &str, panel: &Panel) -> Transition { + fn on_click( + &mut self, + ctx: &mut EventCtx, + app: &mut A, + x: &str, + panel: &Panel, + ) -> Transition { match x { "close" => Transition::Pop, "Alternate instructions" => { @@ -67,22 +76,32 @@ impl SimpleState for ImportCity { Transition::Keep } "Import the area from your clipboard" => { - let drive_on_left = !panel.is_checked("driving side"); + let mut cmd = Command::new("../target/debug/one_step_import"); + cmd.arg("boundary.geojson"); + if !panel.is_checked("driving side") { + cmd.arg("--drive_on_left"); + } match grab_geojson_from_clipboard() { - Ok(()) => { - println!("drive on left? {}", drive_on_left); - Transition::Keep - } - Err(err) => { - return Transition::Push(PopupMsg::new( + Ok(()) => Transition::Multi(vec![ + Transition::Replace(RunCommand::new(ctx, app, cmd)), + Transition::Push(PopupMsg::new( ctx, - "Error", + "Ready to import", vec![ - "Couldn't get GeoJSON from your clipboard".to_string(), - err.to_string(), + "The import will now download what's needed and run in the \ + background.", + "No progress bar or way to cancel yet, sorry.", ], - )); - } + )), + ]), + Err(err) => Transition::Push(PopupMsg::new( + ctx, + "Error", + vec![ + "Couldn't get GeoJSON from your clipboard".to_string(), + err.to_string(), + ], + )), } } _ => unreachable!(), @@ -110,3 +129,56 @@ fn grab_geojson_from_clipboard() -> Result<()> { write!(f, "{}", contents)?; Ok(()) } + +struct RunCommand { + cmd: Command, + panel: Panel, +} + +impl RunCommand { + fn new(ctx: &mut EventCtx, _: &A, cmd: Command) -> Box> { + let txt = Text::from(Line("Running command...")); + let panel = ctx.make_loading_screen(txt); + Box::new(RunCommand { cmd, panel }) + } +} + +impl State for RunCommand { + fn event(&mut self, ctx: &mut EventCtx, _: &mut A) -> Transition { + // TODO Blocking... + // TODO Combo stdout/stderr + info!("Running cmd {:?}", self.cmd); + let (ok, messages) = match self + .cmd + .output() + .map_err(|err| anyhow::Error::new(err)) + .and_then(|out| { + let status = out.status; + String::from_utf8(out.stdout) + .map(|stdout| (status, stdout)) + .map_err(|err| err.into()) + }) { + Ok((status, stdout)) => { + // TODO Split by newlines + if status.success() { + (true, vec!["Output:".to_string(), stdout]) + } else { + (false, vec!["Command failed. Output:".to_string(), stdout]) + } + } + Err(err) => ( + false, + vec!["Couldn't run command".to_string(), err.to_string()], + ), + }; + Transition::Replace(PopupMsg::new( + ctx, + if ok { "Success" } else { "Failure" }, + messages, + )) + } + + fn draw(&self, g: &mut GfxCtx, _: &A) { + self.panel.draw(g); + } +}