// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:io'; import 'dart:convert' show UTF8; import 'package:archive/archive.dart'; import 'package:path/path.dart' as path; import 'base/process.dart'; abstract class ZipBuilder { factory ZipBuilder() { if (exitsHappy(<String>['which', 'zip'])) { return new _ZipToolBuilder(); } else { return new _ArchiveZipBuilder(); } } ZipBuilder._(); List<ZipEntry> entries = <ZipEntry>[]; void addEntry(ZipEntry entry) => entries.add(entry); void createZip(File outFile, Directory zipBuildDir); } class ZipEntry { ZipEntry.fromFile(this.archivePath, File file) { this._file = file; } ZipEntry.fromString(this.archivePath, String contents) { this._contents = contents; } final String archivePath; File _file; String _contents; bool get isStringEntry => _contents != null; } class _ArchiveZipBuilder extends ZipBuilder { _ArchiveZipBuilder() : super._(); @override void createZip(File outFile, Directory zipBuildDir) { Archive archive = new Archive(); for (ZipEntry entry in entries) { if (entry.isStringEntry) { List<int> data = UTF8.encode(entry._contents); archive.addFile(new ArchiveFile.noCompress(entry.archivePath, data.length, data)); } else { List<int> data = entry._file.readAsBytesSync(); archive.addFile(new ArchiveFile(entry.archivePath, data.length, data)); } } List<int> zipData = new ZipEncoder().encode(archive); outFile.writeAsBytesSync(zipData); } } class _ZipToolBuilder extends ZipBuilder { _ZipToolBuilder() : super._(); @override void createZip(File outFile, Directory zipBuildDir) { if (outFile.existsSync()) outFile.deleteSync(); if (zipBuildDir.existsSync()) zipBuildDir.deleteSync(recursive: true); zipBuildDir.createSync(recursive: true); for (ZipEntry entry in entries) { if (entry.isStringEntry) { List<int> data = UTF8.encode(entry._contents); File file = new File(path.join(zipBuildDir.path, entry.archivePath)); file.parent.createSync(recursive: true); file.writeAsBytesSync(data); } else { List<int> data = entry._file.readAsBytesSync(); File file = new File(path.join(zipBuildDir.path, entry.archivePath)); file.parent.createSync(recursive: true); file.writeAsBytesSync(data); } } if (_getCompressedNames().isNotEmpty) { runCheckedSync( <String>['zip', '-q', outFile.absolute.path]..addAll(_getCompressedNames()), workingDirectory: zipBuildDir.path, truncateCommand: true ); } if (_getStoredNames().isNotEmpty) { runCheckedSync( <String>['zip', '-q', '-0', outFile.absolute.path]..addAll(_getStoredNames()), workingDirectory: zipBuildDir.path, truncateCommand: true ); } } Iterable<String> _getCompressedNames() { return entries .where((ZipEntry entry) => !entry.isStringEntry) .map((ZipEntry entry) => entry.archivePath); } Iterable<String> _getStoredNames() { return entries .where((ZipEntry entry) => entry.isStringEntry) .map((ZipEntry entry) => entry.archivePath); } }