| 1296 | } |
| 1297 | |
| 1298 | void Content::unzipAsync(String zipFile, String folderPath, const std::function<bool(String)>& filter, const std::function<void(bool)>& callback) { |
| 1299 | std::error_code err; |
| 1300 | auto fullZipPath = getFullPath(zipFile); |
| 1301 | if (!fs::exists(fullZipPath, err)) { |
| 1302 | Error("\"{}\" must be a local disk zip file to unzip", zipFile.toString()); |
| 1303 | callback(false); |
| 1304 | return; |
| 1305 | } |
| 1306 | if (Content::exist(folderPath)) { |
| 1307 | Error("unzip target \"{}\" existed", folderPath.toString()); |
| 1308 | callback(false); |
| 1309 | return; |
| 1310 | } |
| 1311 | if (!Content::isAbsolutePath(folderPath)) { |
| 1312 | Error("target unzip folder must be of an absolute path instead of \"{}\"", folderPath.toString()); |
| 1313 | callback(false); |
| 1314 | return; |
| 1315 | } |
| 1316 | auto zip = std::make_shared<ZipFile>(fullZipPath); |
| 1317 | if (!zip->isOK()) { |
| 1318 | Error("failed to unzip file \"{}\"", zipFile.toString()); |
| 1319 | callback(false); |
| 1320 | return; |
| 1321 | } |
| 1322 | std::string rootDir; |
| 1323 | BLOCK_START |
| 1324 | auto entries = zip->getDirEntries(""s, false); |
| 1325 | for (const auto& file : entries) { |
| 1326 | if (filter(file)) { |
| 1327 | break; |
| 1328 | } |
| 1329 | } |
| 1330 | auto dirs = zip->getDirEntries(""s, true); |
| 1331 | std::list<std::string> rootDirs; |
| 1332 | for (const auto& dir : dirs) { |
| 1333 | if (filter(dir)) { |
| 1334 | rootDirs.push_back(dir); |
| 1335 | } |
| 1336 | } |
| 1337 | BREAK_IF(rootDirs.size() != 1); |
| 1338 | rootDir = Path::getName(fullZipPath); |
| 1339 | if (rootDirs.front() != rootDir) { |
| 1340 | rootDir.clear(); |
| 1341 | } |
| 1342 | BLOCK_END |
| 1343 | auto files = zip->getAllFiles(); |
| 1344 | std::list<std::string> filtered; |
| 1345 | for (const auto& file : files) { |
| 1346 | if (filter(file)) { |
| 1347 | filtered.push_back(file); |
| 1348 | } |
| 1349 | } |
| 1350 | SharedAsyncThread.run([zip = std::move(zip), folderPath = folderPath.toString(), files = std::move(filtered), zipFile = zipFile.toString(), rootDir, this]() { |
| 1351 | for (const auto& file : files) { |
| 1352 | auto path = Path::concat({folderPath, rootDir.empty() ? file : Path::getRelative(file, rootDir)}); |
| 1353 | if (auto parent = Path::getPath(path); !exist(parent)) { |
| 1354 | createFolder(parent); |
| 1355 | } |
no test coverage detected