1616 Iterable ,
1717 TypeVar ,
1818 Generic ,
19+ Type ,
1920)
2021
2122from fs .base import FS
@@ -220,6 +221,8 @@ def _write_data(data: bytes, stream: BinaryIO) -> int:
220221
221222
222223def _get_or_write_name (name : str , stream : BinaryIO , lookup : Dict [str , int ]) -> int :
224+ # Tools don't like "/" so coerce "/" to "\"
225+ name = name .replace ("/" , "\\ " )
223226 if name in lookup :
224227 return lookup [name ]
225228
@@ -399,7 +402,7 @@ def assemble_drive(
399402 drive_folder_index = drive_def .root_folder - folder_offset
400403 drive_folder_def = local_folder_defs [drive_folder_index ]
401404
402- drive = essence_fs .create_drive (drive_def .alias )
405+ drive = essence_fs .create_drive (drive_def .alias , drive_def . name )
403406 self ._assemble_container (
404407 drive ,
405408 drive_folder_def .file_range ,
@@ -508,41 +511,70 @@ def flatten_folder_collection(self, container_fs: FS, path: str) -> Tuple[int, i
508511 self .flat_folders [subfolder_start :subfolder_end ] = subfolder_defs
509512 return subfolder_start , subfolder_end
510513
514+ def _flatten_folder_names (self , fs : FS , path : str ) -> None :
515+ folders = [file_info .name for file_info in fs .scandir ("/" ) if file_info .is_dir ]
516+ files = [file_info .name for file_info in fs .scandir ("/" ) if file_info .is_file ]
517+
518+ if len (path ) > 0 and path [0 ] == "/" :
519+ path = path [1 :] # strip leading '/'
520+ _get_or_write_name (path , self .name_stream , self .flat_names )
521+
522+ for fold_path in folders :
523+ full_fold_path = f"{ path } /{ fold_path } "
524+ full_fold_path = str (full_fold_path ).split (":" , 1 )[
525+ - 1
526+ ] # Strip 'alias:' from path
527+ if full_fold_path [0 ] == "/" :
528+ full_fold_path = full_fold_path [1 :] # strip leading '/'
529+ _get_or_write_name (full_fold_path , self .name_stream , self .flat_names )
530+
531+ for file_path in files :
532+ _get_or_write_name (file_path , self .name_stream , self .flat_names )
533+
511534 def disassemble_folder (self , folder_fs : FS , path : str ) -> FolderDef :
512535 folder_def = FolderDef (None , None , None ) # type: ignore
513-
514- # Subfiles
515- subfile_range = self .flatten_file_collection (folder_fs )
516- # Subfolders
517- # # Since Relic typically uses the first folder as the root folder; I will try to preserve that parent folders come before their child folders
518- subfolder_range = self .flatten_folder_collection (folder_fs , path )
536+ # Write Name
537+ self ._flatten_folder_names (folder_fs , path )
519538
520539 folder_name = str (path ).split (":" , 1 )[- 1 ] # Strip 'alias:' from path
521-
522540 if folder_name [0 ] == "/" :
523541 folder_name = folder_name [1 :] # strip leading '/'
524-
525542 folder_def .name_pos = _get_or_write_name (
526543 folder_name , self .name_stream , self .flat_names
527544 )
545+
546+ # Subfolders
547+ # # Since Relic typically uses the first folder as the root folder; I will try to preserve that parent folders come before their child folders
548+ subfolder_range = self .flatten_folder_collection (folder_fs , path )
549+
550+ # Subfiles
551+ subfile_range = self .flatten_file_collection (folder_fs )
552+
528553 folder_def .file_range = subfile_range
529554 folder_def .folder_range = subfolder_range
530555
531556 return folder_def
532557
533- def disassemble_drive (self , drive : _EssenceDriveFS , alias : str ) -> DriveDef :
534- name = ""
558+ def disassemble_drive (self , drive : _EssenceDriveFS ) -> DriveDef :
559+ name = drive .name
560+ folder_name = ""
561+ alias = drive .alias
535562 drive_folder_def = FolderDef (None , None , None ) # type: ignore
563+ self ._flatten_folder_names (drive , folder_name )
564+
536565 root_folder = len (self .flat_folders )
537566 folder_start = len (self .flat_folders )
538567 file_start = len (self .flat_files )
539568 self .flat_folders .append (drive_folder_def )
540569
570+ # Name should be an empty string?
541571 drive_folder_def .name_pos = _get_or_write_name (
542- name , self .name_stream , self .flat_names
572+ folder_name , self .name_stream , self .flat_names
543573 )
544574 drive_folder_def .file_range = self .flatten_file_collection (drive )
545- drive_folder_def .folder_range = self .flatten_folder_collection (drive , name )
575+ drive_folder_def .folder_range = self .flatten_folder_collection (
576+ drive , folder_name
577+ )
546578
547579 folder_end = len (self .flat_folders )
548580 file_end = len (self .flat_files )
@@ -593,9 +625,9 @@ def write_toc(self) -> TocBlock:
593625 )
594626
595627 def disassemble (self ) -> TocBlock :
596- for name , drive_fs in self .fs .iterate_fs ():
628+ for _ , drive_fs in self .fs .iterate_fs ():
597629 drive_fs = typing .cast (_EssenceDriveFS , drive_fs )
598- drive_def = self .disassemble_drive (drive_fs , name )
630+ drive_def = self .disassemble_drive (drive_fs )
599631 self .flat_drives .append (drive_def )
600632
601633 return self .write_toc ()
@@ -740,6 +772,8 @@ def __init__(
740772 gen_empty_meta : Callable [[], TMetaBlock ],
741773 finalize_meta : Callable [[BinaryIO , TMetaBlock ], None ],
742774 meta2def : Callable [[Dict [str , object ]], TFileDef ],
775+ assembler : Optional [Type [FSAssembler [TFileDef ]]] = None ,
776+ disassembler : Optional [Type [FSDisassembler [TFileDef ]]] = None ,
743777 ):
744778 self .version = version
745779 self .meta_serializer = meta_serializer
@@ -752,6 +786,8 @@ def __init__(
752786 self .gen_empty_meta = gen_empty_meta
753787 self .finalize_meta = finalize_meta
754788 self .meta2def = meta2def
789+ self .assembler_type = assembler or FSAssembler
790+ self .disassembler_type = disassembler or FSDisassembler
755791
756792 def read (self , stream : BinaryIO ) -> EssenceFS :
757793 # Magic & Version; skippable so that we can check for a valid file and read the version elsewhere
@@ -773,7 +809,7 @@ def read(self, stream: BinaryIO) -> EssenceFS:
773809 name , metadata = meta_block .name , self .assemble_meta (
774810 stream , meta_block , toc_meta_block
775811 )
776- assembler : FSAssembler [TFileDef ] = FSAssembler (
812+ assembler : FSAssembler [TFileDef ] = self . assembler_type (
777813 stream = stream ,
778814 ptrs = meta_block .ptrs ,
779815 toc = toc_block ,
@@ -806,7 +842,7 @@ def write(self, stream: BinaryIO, essence_fs: EssenceFS) -> int:
806842 with BytesIO () as data_stream :
807843 with BytesIO () as toc_stream :
808844 with BytesIO () as name_stream :
809- disassembler = FSDisassembler (
845+ disassembler : FSDisassembler [ TFileDef ] = self . disassembler_type (
810846 fs = essence_fs ,
811847 toc_stream = toc_stream ,
812848 data_stream = data_stream ,
0 commit comments