diff --git a/3rdparty/interface/archiveinterface/cliinterface.cpp b/3rdparty/interface/archiveinterface/cliinterface.cpp index 651366ab..177a9ef4 100644 --- a/3rdparty/interface/archiveinterface/cliinterface.cpp +++ b/3rdparty/interface/archiveinterface/cliinterface.cpp @@ -1098,6 +1098,59 @@ bool CliInterface::moveExtractTempFilesToDest(const QList &files, con return moveSuccess; } +void CliInterface::removeExtractedFilesOnFailure(const QString &strTargetPath, const QList &entries) +{ + QList listToRemove = entries; + if (listToRemove.isEmpty()) { + listToRemove = DataManager::get_instance().archiveData().mapFileEntry.values(); + } + if (listToRemove.isEmpty()) { + return; + } + + QDir targetDir(strTargetPath); + if (!targetDir.exists()) { + return; + } + + QList > paths; // path, isDirectory + for (const FileEntry &entry : listToRemove) { + QString relPath = entry.strFullPath; + if (relPath.endsWith(QLatin1Char('/'))) { + relPath.chop(1); + } + if (relPath.isEmpty()) { + continue; + } + paths.append(qMakePair(targetDir.absoluteFilePath(relPath), entry.isDirectory)); + } + + for (const auto &p : paths) { + const QString &path = p.first; + if (!p.second) { // 文件 + QFileInfo fi(path); + if (fi.exists() && fi.isFile() && fi.size() == 0) { + QFile::remove(path); + } + } + } + // 空目录可能有多层,循环直到本轮没有可删的空目录 + bool removed; + do { + removed = false; + for (const auto &p : paths) { + if (!p.second) { + continue; + } + QDir d(p.first); + if (d.exists() && d.isEmpty()) { + d.removeRecursively(); + removed = true; + } + } + } while (removed); +} + bool CliInterface::handleLongNameExtract(const QList &files) { ExtractionOptions &options = m_extractOptions; @@ -1272,6 +1325,7 @@ void CliInterface::readStdout(bool handleAll) // 第二个判断条件是处理rar的list,当rar文件含有comment信息的时候需要根据空行解析 if (!line.isEmpty() || (m_listEmptyLines && m_workStatus == WT_List)) { if (!handleLine(QString::fromLocal8Bit(line), m_workStatus)) { + emit signalprogress(100); killProcess(); return; } @@ -1316,6 +1370,11 @@ void CliInterface::extractProcessFinished(int exitCode, QProcess::ExitStatus exi m_indexOfListRootEntry = 0; m_isEmptyArchive = false; + // 解压失败(如分卷加密包输错密码)且为全部解压到目标路径时,清理已生成的 size 为 0 等残留文件 + if (0 != exitCode && m_extractOptions.bAllExtract && !m_extractOptions.strTargetPath.isEmpty()) { + removeExtractedFilesOnFailure(m_extractOptions.strTargetPath, m_files); + } + if (!m_extractOptions.bAllExtract && (!(m_extractOptions.strTargetPath.startsWith("/tmp") && m_extractOptions.strTargetPath.contains("/deepin-compressor-") && m_extractOptions.strDestination.isEmpty()))) { if (0 == exitCode) { // job正常结束 // 提取操作和打开解压列表文件非第一层的文件 diff --git a/3rdparty/interface/archiveinterface/cliinterface.h b/3rdparty/interface/archiveinterface/cliinterface.h index ac9a4066..8b934e40 100644 --- a/3rdparty/interface/archiveinterface/cliinterface.h +++ b/3rdparty/interface/archiveinterface/cliinterface.h @@ -193,6 +193,13 @@ class CliInterface : public ReadWriteArchiveInterface */ bool moveExtractTempFilesToDest(const QList &files, const ExtractionOptions &options); + /** + * @brief removeExtractedFilesOnFailure 解压失败时清理已生成的文件(如分卷加密包输错密码时产生的 size 为 0 的文件) + * @param strTargetPath 解压目标路径 + * @param entries 本次解压涉及的条目列表(可为空,为空时从 ArchiveData 获取全部) + */ + void removeExtractedFilesOnFailure(const QString &strTargetPath, const QList &entries); + bool handleLongNameExtract(const QList &files); private slots: