chiark / gitweb /
library listing: Rework library patterns
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 May 2021 22:42:57 +0000 (23:42 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 15 May 2021 23:32:13 +0000 (00:32 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
apitest/at-otter.rs
daemon/cmdlistener.rs
src/bin/otter.rs
src/commands.rs
src/mgmtchannel.rs

index 646ae347e64d7b71b02d76936fef825faa24e049..c3b8bfad4da1b49fca8dd70db451baf9f332e3da 100644 (file)
@@ -543,7 +543,7 @@ impl Ctx {
     prepare_game(&self.su().ds, &self.prctx, TABLE)?;
 
     let command = self.su().ds.ss(
-      "library-list @table@ wikimedia chess-yellow-?"
+      "library-list @table@ chess-yellow-?"
     )?;
     let output: String = self.otter(&command)?.into();
     assert!( Regex::new("(?m)^wikimedia  *chess-yellow-K  *the yellow king$")?
@@ -552,7 +552,7 @@ impl Ctx {
              "got: {}", &output);
 
     let command = self.su().ds.ss(
-      "library-add @table@ wikimedia chess-blue-?"
+      "library-add --lib wikimedia @table@ chess-blue-?"
     )?;
     let added = self.some_library_add(&command)?;
     assert_eq!(added.len(), 6);
@@ -733,7 +733,7 @@ impl Ctx {
     let st = Command::new("cmp").args(&[&bundle_file, "00000.zip"]).status()?;
     if ! st.success() { panic!("cmp failed {}", st) }
 
-    let command = ds.ss("library-add @table@ lemon example-lemon")?;
+    let command = ds.ss("library-add --lib lemon @table@ example-lemon")?;
     let added = self.some_library_add(&command)?;
     assert_eq!( added.len(), 1 );
 
index 9f29763a3030752c2e1c7fe1e6cbdcc76f2efe6c..9b354037510b8c52ffe023e0020b291c310b298f 100644 (file)
@@ -368,17 +368,23 @@ fn execute_and_respond<R,W>(cs: &mut CommandStreamData, cmd: MgmtCommand,
       MR::Libraries(libs)
     }
 
-    MC::LibraryListByGlob { game, glob: spec } => {
+    MC::LibraryListByGlob { game, lib, pat } => {
       let (ag, gref) = start_access_game(&game)?;
       let (results, _auth) =
         access_bundles(
           cs,&ag,&gref, &[TP::UploadBundles],
           &mut |ig, _| {
             let regs = ig.all_shapelibs();
-            let libs = regs.lib_name_lookup(&spec.lib)?;
             let mut results: Vec<shapelib::ItemEnquiryData> = default();
-            for lib in &*libs {
-              results.extend(lib.list_glob(&spec.item)?);
+            let libss = if let Some(lib) = &lib {
+              vec![regs.lib_name_lookup(lib)?]
+            } else {
+              regs.all_libs().collect()
+            };
+            for libs in libss {
+              for lib in libs {
+                results.extend(lib.list_glob(&pat)?);
+              }
             }
             Ok(results)
           })?;
index 98d05ce94bf66c780f1649caaa55674d7ce795bc..514b3de3a21026bbe0856ce1735bd1ce04e0f63d 100644 (file)
@@ -991,17 +991,13 @@ mod delete_game {
 
 //---------- library-list ----------
 
-#[derive(Debug)]
+#[derive(Debug,Default)]
 struct LibGlobArgs {
   table_name: String,
-  pat: shapelib::ItemSpec,
+  lib: Option<String>,
+  pat: Option<String>,
 }
 
-impl Default for LibGlobArgs { fn default() -> Self { Self {
-  table_name: default(),
-  pat: shapelib::ItemSpec { lib: default(), item: default() },
-} } }
-
 impl LibGlobArgs {
   fn add_arguments<'ap, 'tlg: 'ap>(
     &'tlg mut self,
@@ -1010,12 +1006,19 @@ impl LibGlobArgs {
     use argparse::*;
     ap.refer(&mut self.table_name).required()
       .add_argument("TABLE-NAME",Store,"table name");
-    // xxx allow lack of library name to list library names
-    ap.refer(&mut self.pat.lib).required()
-      .add_argument("LIB-NAME",Store,"library name");
-    // xxx allow lack of pattern to list whole library
-    ap.refer(&mut self.pat.item).required()
-      .add_argument("ITEM-GLOB-PATTERN",Store,"item glob pattern");
+    ap.refer(&mut self.lib).metavar("LIBRARY")
+      .add_option(&["--lib"],StoreOption,"look only in LIBRARY");
+    ap.refer(&mut self.pat)
+      .add_argument("ITEM-GLOB-PATTERN",StoreOption,"item glob pattern");
+  }
+
+  fn lib(&self) -> Option<String> {
+    self.lib.clone()
+  }
+  fn pat(&self) -> String {
+    self.pat.as_ref().map(Deref::deref)
+      .unwrap_or("*")
+      .into()
   }
 }
 
@@ -1036,7 +1039,20 @@ mod library_list {
     let args = parse_args::<Args,_>(args, &subargs, &ok_id, None);
     let mut chan = access_game(&ma, &args.table_name)?;
 
-    let items = chan.list_items(&args.pat)?;
+    if args.lib.is_none() && args.pat.is_none() {
+      let game = chan.game.clone();
+      let libs = match chan.cmd(&MC::LibraryListLibraries { game })? {
+        MgmtResponse::Libraries(libs) => libs,
+        x => throw!(anyhow!(
+          "unexpected response to LibrarylistLibraries: {:?}", &x)),
+      };
+      for lib in libs {
+        println!("{}", lib);
+      }
+      return;
+    }
+
+    let items = chan.list_items(args.lib.clone(), args.pat())?;
     for it in &items {
       println!("{}", it);
     }
@@ -1245,7 +1261,7 @@ mod library_add {
       }
     }
 
-    let items = chan.list_items(&args.tlg.pat)?;
+    let items = chan.list_items(args.tlg.lib(), args.tlg.pat())?;
 
     let mut exitcode = 0;
     let mut insns = vec![];
@@ -1272,7 +1288,7 @@ mod library_add {
         }
       };
       let spec = shapelib::ItemSpec {
-        lib: args.tlg.pat.lib.clone(),
+        lib: it.libname.clone(),
         item: it.itemname.as_str().to_owned(),
       };
       let spec = PiecesSpec {
index 6c02d48cc55ebaa01974353ac08a26fbbccad3f4..38d5a17e25111113b4961415543bf16d917af014 100644 (file)
@@ -59,7 +59,8 @@ pub enum MgmtCommand {
   },
   LibraryListByGlob {
     game: InstanceName,
-    glob: shapelib::ItemSpec,
+    lib: Option<String>,
+    pat: String,
   },
 
   LoadFakeRng(Vec<String>),
index 0edb7470767b2919c0ec4bc88e012d63dc5b2b8f..be4547f90a3f3077f8359d62b30e62c53ac0ce0a 100644 (file)
@@ -212,12 +212,12 @@ impl MgmtChannelForGame {
   }
 
   #[throws(AE)]
-  pub fn list_items(&mut self, pat: &shapelib::ItemSpec)
+  pub fn list_items(&mut self, lib: Option<String>, pat: String)
                 -> Vec<shapelib::ItemEnquiryData> {
     // xxx allow globbing of library names
     let cmd = MgmtCommand::LibraryListByGlob {
       game: self.game.clone(),
-      glob: pat.clone(),
+      lib, pat,
     };
     let mut items = match self.cmd(&cmd)? {
       MgmtResponse::LibraryItems(items) => items,