chiark / gitweb /
thunkify and move local directory finding
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 21 Nov 2020 18:32:47 +0000 (18:32 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 21 Nov 2020 18:32:47 +0000 (18:32 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bin/daemon-otter.rs
src/bin/otter.rs
src/config.rs

index 76104cc8b4a71223b05ea10b0f9dbe2914739f9c..95e2fa8ce5bb6825fd049619596585093cc8c944 100644 (file)
@@ -106,7 +106,7 @@ fn main() {
   // todo test suite for web api
 
   let config_filename = env::args().nth(1);
-  ServerConfig::read(config_filename.as_ref().map(String::as_str))?;
+  ServerConfig::read(config_filename.as_ref().map(String::as_str), true)?;
 
   std::env::set_var("ROCKET_CLI_COLORS","off");
 
index 3dfb81620dee80cd62f3ef81dd25c011d992238b..672639c2b665756d4e700a5ca545b55fb65ef063 100644 (file)
@@ -58,15 +58,6 @@ impl<'x, T, F: FnMut(&str) -> Result<T,String>>
   }
 }
 
-mod exits {
-  #![allow(dead_code)]
-  pub const EXIT_SPACE     : i32 =  2;
-  pub const EXIT_SITUATION : i32 =  8;
-  pub const EXIT_USAGE     : i32 = 12;
-  pub const EXIT_DISASTER  : i32 = 16;
-}
-use exits::*;
-
 #[derive(Debug)]
 struct MainOpts {
   account: AccountName,
@@ -272,35 +263,11 @@ fn main() {
         subaccount: "".into(),
       })
     })?;
-    let config_filename = config_filename.or_else(||{
-      match match env::current_exe()
-        .map(|p| p.to_str().map(|s| s.to_string()))
-      {
-        Err(e) => Err(format!(
-          "could not find current executable ({})", &e
-        )),
-        Ok(None) => Err(format!(
-          "current executable has non-UTF8 filename!"
-        )),
-        Ok(Some(basedir)) if basedir.rsplit('/').nth(1) == Some("bin") => Ok(
-          format!("{}/etc/{}", basedir, DEFAULT_CONFIG_FILENAME)
-        ),
-        Ok(_) => Err(format!(
-          "current executable is not in a directory called bin"
-        )),
-      } {
-        Err(whynot) => {
-          if verbose > 1 {
-            eprintln!("{}: looking for {} in current directory",
-                      &whynot, DEFAULT_CONFIG_FILENAME);
-          }
-          None
-        },
-        Ok(f) => Some(f),
-      }
-    });
     let config = Thunk::new(||{
-      ServerConfig::read(config_filename.as_ref().map(String::as_str))
+      ServerConfig::read(
+        config_filename.as_ref().map(String::as_str),
+        verbose > 1
+      )
         .context("read config file")?;
       Ok::<_,AE>(otter::config::config())
     });
index 7498dfa9ecd9f04c0ae3ea878cd7de6668f40589..eece6441a152d7901bd65679684afe54c8c6f818 100644 (file)
@@ -4,6 +4,11 @@
 
 use crate::imports::*;
 
+pub const EXIT_SPACE     : i32 =  2;
+pub const EXIT_SITUATION : i32 =  8;
+pub const EXIT_USAGE     : i32 = 12;
+pub const EXIT_DISASTER  : i32 = 16;
+
 pub const DEFAULT_CONFIG_FILENAME : &str = "server.toml";
 
 const DEFAULT_SAVE_DIRECTORY : &str = "save";
@@ -109,11 +114,63 @@ fn set_config(config: ServerConfig) {
   *GLOBAL.config.write().unwrap() = Arc::new(config)
 }
 
+fn default_basedir_from_executable(verbose: bool) -> Option<String> {
+  #[throws(StartupError)]
+  fn inner(verbose: bool) -> Option<String> {
+    match match env::current_exe()
+      .map(|p| p.to_str().map(|s| s.to_string()))
+    {
+      Err(e) => Err(format!(
+        "could not find current executable ({})", &e
+      )),
+      Ok(None) => Err(format!(
+        "current executable has non-UTF8 filename!"
+      )),
+      Ok(Some(basedir)) if basedir.rsplit('/').nth(1) == Some("bin") => Ok(
+        format!("{}/", basedir)
+      ),
+      Ok(_) => Err(format!(
+        "current executable is not in a directory called bin"
+      )),
+    } {
+      Err(whynot) => {
+        if verbose {
+          eprintln!("{}: looking for ancillary files in current directory",
+                    &whynot);
+        }
+        None
+      },
+      Ok(f) => Some(f),
+    }
+  }
+
+  inner(verbose).unwrap_or_else(|e|{
+    eprintln!("startup error finding installation pieces: {}", &e);
+    exit(EXIT_DISASTER)
+  })
+}
+
+fn in_basedir<F: Sync + FnOnce() -> Option<String>>
+  (basedir: &mut Thunk<Option<String>,F>,
+   subdir: &str,
+   localdir: &str,
+   leaf: &str) -> String
+{
+  match basedir.as_ref() {
+    Some(basedir) => format!("{}/{}/{}", basedir, subdir, leaf),
+    None          => format!(   "{}/{}",        localdir, leaf),
+  }
+}
+
 impl ServerConfig {
   #[throws(StartupError)]
-  pub fn read(config_filename: Option<&str>) {
-    let config_filename = config_filename
-      .unwrap_or_else(|| DEFAULT_CONFIG_FILENAME);
+  pub fn read(config_filename: Option<&str>, verbose: bool) {
+    let mut basedir = Thunk::new(
+      move || default_basedir_from_executable(verbose)
+    );
+    let config_filename = config_filename.map(|s| s.to_string()).unwrap_or_else(
+      || in_basedir(&mut basedir, "etc", "", DEFAULT_CONFIG_FILENAME)
+    );
     let mut buf = String::new();
     File::open(&config_filename).with_context(||config_filename.to_string())?
       .read_to_string(&mut buf)?;