chiark / gitweb /
libraries: Prepare for multiple libraries with the same name
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 5 May 2021 13:07:09 +0000 (14:07 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 5 May 2021 15:08:47 +0000 (16:08 +0100)
This can't currently happen with the global shape libraries but the
per-game ones might have this, if the bundles overlap.  And we
want to use the same data structure.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
src/bin/otterlib.rs
src/shapelib.rs

index 231bf66d7487977dc0d265b00dabe69ed10cc36b..31c5ae9722c81e15bb64cf81e9b3208e677144b1 100644 (file)
@@ -308,8 +308,11 @@ fn execute_and_respond<R,W>(cs: &mut CommandStreamData, cmd: MgmtCommand,
     }
 
     MC::LibraryListByGlob { glob: spec } => {
-      let lib = shapelib::libs_lookup(&spec.lib)?;
-      let results = lib.list_glob(&spec.item)?;
+      let libs = shapelib::lib_name_lookup(&spec.lib)?;
+      let mut results: Vec<shapelib::ItemEnquiryData> = default();
+      for lib in &*libs {
+        results.extend(lib.list_glob(&spec.item)?);
+      }
       MR::LibraryItems(results)
     }
 
index 062ef6193d253f7c3a3c6f707d7d40f61b84e886..bcb325a60cde2d541607b74d715a2c529ee06077 100644 (file)
@@ -232,11 +232,12 @@ fn main() {
     load(&vec![tlibs.clone()])?;
   }
   let mut items: Vec<ItemForOutput> = default();
-  for lib in libs_list() {
-    let contents = libs_lookup(&lib)?;
-    for pat in opts.items.split(SPLIT) {
-      for item in contents.list_glob(pat)? {
-        items.push((lib.clone(), item))
+  for lib in lib_name_list() {
+    for contents in &*lib_name_lookup(&lib)? {
+      for pat in opts.items.split(SPLIT) {
+        for item in contents.list_glob(pat)? {
+          items.push((lib.clone(), item))
+        }
       }
     }
   }
index 145bd5b8dcb3e0e459b3b9f43107f0336b3b1d48..0e7a550ed84d0da3862ed49f4d30ca9d6aecef98 100644 (file)
@@ -17,7 +17,7 @@ use parking_lot::{MappedRwLockReadGuard, RwLockReadGuard};
 
 #[derive(Default)]
 pub struct Registry {
-  libs: HashMap<String, shapelib::Contents>,
+  libs: HashMap<String, Vec<shapelib::Contents>>,
 }
 
 #[derive(Debug)]
@@ -316,7 +316,7 @@ impl OccultedPieceTrait for Item {
 
 static SHAPELIBS: RwLock<Option<Registry>> = const_rwlock(None);
 
-pub fn libs_list() -> Vec<String> {
+pub fn lib_name_list() -> Vec<String> {
   let reg = SHAPELIBS.read();
   reg.as_ref().map(
     |reg| reg.libs.keys().cloned().collect()
@@ -324,12 +324,13 @@ pub fn libs_list() -> Vec<String> {
 }
 
 #[throws(SpecError)]
-pub fn libs_lookup(libname: &str)
-                   -> MappedRwLockReadGuard<'static, Contents> {
+pub fn lib_name_lookup(libname: &str)
+                   -> MappedRwLockReadGuard<'static, [Contents]> {
   let reg = SHAPELIBS.read();
   RwLockReadGuard::try_map( reg, |reg: &Option<Registry>| -> Option<_> {
     (|| Some({
       reg.as_ref()?.libs.get(libname)?
+        .as_slice()
     }))()
   })
     .map_err(|_| SpE::LibraryNotFound)
@@ -351,8 +352,10 @@ impl From<ItemSpecLoaded> for PieceSpecLoaded {
 impl ItemSpec {
   #[throws(SpecError)]
   pub fn find_load(&self, pcaliases: &PieceAliases) -> ItemSpecLoaded {
-    let lib = libs_lookup(&self.lib)?;
-    let idata = lib.items.get(&self.item)
+    let libs = lib_name_lookup(&self.lib)?;
+    let (lib, idata) = libs.iter().rev().find_map(
+      |lib| Some((lib, lib.items.get(&self.item)?))
+    )
       .ok_or(SpE::LibraryItemNotFound(self.clone()))?;
     lib.load1(idata, &self.lib, &self.item, pcaliases)?
   }
@@ -723,7 +726,8 @@ pub fn load1(l: &Explicit1) {
   SHAPELIBS.write()
     .get_or_insert_with(default)
     .libs
-    .insert(l.name.clone(), data);
+    .entry(l.name.clone()).or_default()
+    .push(data);
   info!("loaded {} shapes in library {:?} from {:?} and {:?}",
         count, &l.name, &l.catalogue, &l.dirname);
 }