Add app source and tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
34
lib/Peach/about/internal/file/WebArchive.dart
Normal file
34
lib/Peach/about/internal/file/WebArchive.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:archive/archive_io.dart';
|
||||
|
||||
/// Packs a directory of static files into a gzip-compressed tar archive
|
||||
/// (contents at the archive root) for a single-shot upload + remote extract.
|
||||
class WebArchive {
|
||||
/// Returns the .tar.gz bytes of [dir]'s contents and the number of files.
|
||||
static (Uint8List, int) tarGz(Directory dir) {
|
||||
final archive = createArchiveFromDirectory(dir, includeDirName: false);
|
||||
// CRITICAL: on Windows the entry names use backslashes; a POSIX `tar` on
|
||||
// the server would then create single files literally named
|
||||
// `assets\main.js` instead of the `assets/main.js` tree — breaking any
|
||||
// app with subdirectories (Angular/React assets, etc.). Force forward
|
||||
// slashes so the archive is valid on Linux.
|
||||
for (final f in archive.files) {
|
||||
f.name = f.name.replaceAll('\\', '/');
|
||||
}
|
||||
final tar = TarEncoder().encode(archive);
|
||||
final gz = GZipEncoder().encode(tar);
|
||||
final count = archive.files.where((f) => f.isFile).length;
|
||||
// Release the file handles opened while reading the directory so the
|
||||
// source tree isn't left locked (notably on Windows).
|
||||
for (final f in archive.files) {
|
||||
f.closeSync();
|
||||
}
|
||||
return (Uint8List.fromList(gz), count);
|
||||
}
|
||||
}
|
||||
|
||||
/// Top-level entry so packaging can run off the UI isolate via `compute`.
|
||||
(Uint8List, int) packageWebDir(String path) =>
|
||||
WebArchive.tarGz(Directory(path));
|
||||
Reference in New Issue
Block a user