archive icon indicating copy to clipboard operation
archive copied to clipboard

there should be an addDirectory method on the Archive class

Open csells opened this issue 4 years ago • 1 comments

I seem to be able to add directories to an encoder but not an archive. This seems to work in my limited testing:

  void addArchiveDirectory(Archive arc, String name) =>
        arc.addFile(ArchiveFile(name, 0, <int>[])
          ..isFile = false
          ..compress = false
          ..mode = 0x41FD
          ..crc32 = 0);

Is this the correct way to add a directory to an Archive?

I use this technique in an extension I added on Archive:

extension on Archive {
  static final encoder = JsonEncoder.withIndent('  ');
  void addJsonFileFromList(String name, List<dynamic> list) => addTextFileFromText(name, encoder.convert(list));
  void addJsonFileFromMap(String name, Map<String, dynamic> map) => addTextFileFromText(name, encoder.convert(map));
  void addTextFileFromText(String name, String text) => addBinaryFileFromBytes(name, utf8.encode(text) as Uint8List);

  void addBinaryFileFromBytes(String name, Uint8List bytes) {
    if (name == null || name.isEmpty) throw Exception('name cannot be null or empty');
    if (name.startsWith('/')) throw Exception('name cannot start with / ($name)');
    if (name.endsWith('/')) throw Exception('name cannot end with / ($name)');

    // add directory implied by the file
    final index = name.lastIndexOf('/');
    if (index != -1) addDirectory(name.substring(0, index + 1));

    // add the actual file
    addFile(ArchiveFile(name, bytes.length, bytes));
  }

  void addDirectory(String name, {bool recursive = true}) {
    if (name == null || name.isEmpty) throw Exception('name cannot be null or empty');
    if (name.startsWith('/')) throw Exception('name cannot start with / ($name)');
    if (!name.endsWith('/')) throw Exception('name must end with / ($name)');

    final dirs = <String>[];
    if (recursive) {
      final parts = name.split('/');
      var partial = '';
      for (final part in parts) {
        partial += '$part/';
        dirs.add(partial);
      }
    } else {
      dirs.add(name);
    }

    for (final dir in dirs) {
      final file = findFile(dir);
      if (file == null) {
        addFile(ArchiveFile(dir, 0, <int>[])
          ..isFile = false
          ..compress = false
          ..mode = 0x41FD
          ..crc32 = 0);
      }
    }
  }
}

Feel free to use any of that you find useful.

csells avatar Sep 05 '20 15:09 csells

+1. Is the above recommended by the authors? Should it be added to the plugin?

intonarumori avatar May 21 '23 15:05 intonarumori