Skip to content

Commit fdb26ba

Browse files
LiHua000deepin-bot[bot]
authored andcommitted
fix: keep renamed file content during compression
- copy aliased entries into a temp directory before invoking createArchive - update FileEntry paths to point at the real copies and clear aliases - cleanup the temp copies on success, failure, cancel, and reset - ensures libzip sees actual files instead of symlink paths Log: fix bug Bug: https://pms.uniontech.com/bug-view-340081.html
1 parent 2d870ff commit fdb26ba

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

src/source/mainwindow.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@
5050
#include <QShortcut>
5151
#include <QJsonObject>
5252
#include <QTimer>
53+
#include <QFile>
54+
#include <QFileInfo>
55+
#include <QDir>
56+
#include <QDirIterator>
57+
#include <QUuid>
5358
#ifdef DTKCORE_CLASS_DConfigFile
5459
#include <DConfig>
5560
DCORE_USE_NAMESPACE
@@ -58,6 +63,40 @@ DCORE_USE_NAMESPACE
5863
static QMutex mutex; // 静态全局变量只在定义该变量的源文件内有效
5964
#define FILE_TRUNCATION_LENGTH 70
6065

66+
namespace {
67+
68+
bool copyDirectoryRecursively(const QString &sourcePath, const QString &targetPath)
69+
{
70+
QDir sourceDir(sourcePath);
71+
if (!sourceDir.exists()) {
72+
return false;
73+
}
74+
75+
if (!QDir().mkpath(targetPath)) {
76+
return false;
77+
}
78+
79+
const QFileInfoList entries = sourceDir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files | QDir::Hidden | QDir::System);
80+
for (const QFileInfo &info : entries) {
81+
const QString srcFilePath = info.absoluteFilePath();
82+
const QString dstFilePath = targetPath + QDir::separator() + info.fileName();
83+
if (info.isDir()) {
84+
if (!copyDirectoryRecursively(srcFilePath, dstFilePath)) {
85+
return false;
86+
}
87+
} else {
88+
QFile::remove(dstFilePath);
89+
if (!QFile::copy(srcFilePath, dstFilePath)) {
90+
return false;
91+
}
92+
}
93+
}
94+
95+
return true;
96+
}
97+
98+
} // namespace
99+
61100
MainWindow::MainWindow(QWidget *parent)
62101
: DMainWindow(parent)
63102
, m_strProcessID(QString::number(QCoreApplication::applicationPid())) // 获取应用进程号
@@ -1015,6 +1054,11 @@ void MainWindow::slotCompress(const QVariant &val)
10151054

10161055
// 构建压缩文件数据
10171056
listEntry = m_pCompressPage->getEntrys();
1057+
1058+
if (!prepareCompressAliasEntries(listEntry)) {
1059+
return;
1060+
}
1061+
10181062
strDestination = m_stCompressParameter.strTargetPath + QDir::separator() + m_stCompressParameter.strArchiveName;
10191063

10201064
// 构建压缩参数
@@ -1089,6 +1133,7 @@ void MainWindow::slotCompress(const QVariant &val)
10891133
m_ePageID = PI_CompressProgress;
10901134
refreshPage();
10911135
} else {
1136+
cleanupCompressAliasEntries();
10921137
// 无可用插件
10931138
showErrorMessage(FI_Compress, EI_NoPlugin);
10941139
}
@@ -1305,6 +1350,8 @@ void MainWindow::handleJobNormalFinished(ArchiveJob::JobType eType, ErrorType eE
13051350

13061351
// zip压缩包添加注释
13071352
addArchiveComment();
1353+
1354+
cleanupCompressAliasEntries();
13081355
}
13091356
break;
13101357
// 添加文件至压缩包
@@ -1544,6 +1591,7 @@ void MainWindow::handleJobCancelFinished(ArchiveJob::JobType eType)
15441591
} else {
15451592
m_ePageID = PI_Compress;
15461593
}
1594+
cleanupCompressAliasEntries();
15471595
}
15481596
break;
15491597
// 添加文件至压缩包
@@ -1643,6 +1691,8 @@ void MainWindow::handleJobErrorFinished(ArchiveJob::JobType eJobType, ErrorType
16431691
}
16441692
}
16451693

1694+
cleanupCompressAliasEntries();
1695+
16461696
}
16471697
break;
16481698
// 压缩包追加文件错误
@@ -1938,6 +1988,8 @@ void MainWindow::resetMainwindow()
19381988
maxFileSize_ = 0;
19391989
#endif
19401990

1991+
cleanupCompressAliasEntries();
1992+
19411993
m_ePageID = PI_Home;
19421994
m_operationtype = Operation_NULL; // 重置操作类型
19431995
m_iCompressedWatchTimerID = 0; // 初始化定时器返回值
@@ -2079,6 +2131,92 @@ void MainWindow::ConstructAddOptionsByThread(const QString &path)
20792131
}
20802132
}
20812133

2134+
bool MainWindow::prepareCompressAliasEntries(QList<FileEntry> &listEntry)
2135+
{
2136+
m_needCleanupCompressAlias = false;
2137+
m_strCompressAliasRoot.clear();
2138+
2139+
bool hasAlias = false;
2140+
QString aliasRoot;
2141+
2142+
for (FileEntry &entry : listEntry) {
2143+
if (entry.strAlias.isEmpty()) {
2144+
continue;
2145+
}
2146+
2147+
if (entry.strFullPath.isEmpty()) {
2148+
continue;
2149+
}
2150+
2151+
if (!hasAlias) {
2152+
const QString baseDir = TEMPPATH + QDir::separator() + m_strProcessID + QDir::separator() + "compress_alias";
2153+
if (!QDir().mkpath(baseDir)) {
2154+
showWarningDialog(tr("Failed to create temporary directory, please check and try again."));
2155+
return false;
2156+
}
2157+
aliasRoot = baseDir + QDir::separator() + QUuid::createUuid().toString(QUuid::WithoutBraces);
2158+
if (!QDir().mkpath(aliasRoot)) {
2159+
showWarningDialog(tr("Failed to create temporary directory, please check and try again."));
2160+
return false;
2161+
}
2162+
}
2163+
2164+
const QString aliasName = entry.strAlias;
2165+
const QString targetPath = aliasRoot + QDir::separator() + aliasName;
2166+
2167+
if (entry.isDirectory) {
2168+
QDir(targetPath).removeRecursively();
2169+
if (!copyDirectoryRecursively(entry.strFullPath, targetPath)) {
2170+
showWarningDialog(tr("Failed to prepare renamed item \"%1\" for compression, please check permissions and available space.")
2171+
.arg(aliasName));
2172+
if (!aliasRoot.isEmpty()) {
2173+
QDir(aliasRoot).removeRecursively();
2174+
}
2175+
return false;
2176+
}
2177+
} else {
2178+
QFile::remove(targetPath);
2179+
if (!QFile::copy(entry.strFullPath, targetPath)) {
2180+
showWarningDialog(tr("Failed to prepare renamed item \"%1\" for compression, please check permissions and available space.")
2181+
.arg(aliasName));
2182+
if (!aliasRoot.isEmpty()) {
2183+
QDir(aliasRoot).removeRecursively();
2184+
}
2185+
return false;
2186+
}
2187+
}
2188+
2189+
entry.strFullPath = targetPath;
2190+
entry.strAlias.clear();
2191+
hasAlias = true;
2192+
}
2193+
2194+
if (hasAlias) {
2195+
m_strCompressAliasRoot = aliasRoot;
2196+
m_needCleanupCompressAlias = true;
2197+
} else {
2198+
m_strCompressAliasRoot.clear();
2199+
m_needCleanupCompressAlias = false;
2200+
}
2201+
2202+
return true;
2203+
}
2204+
2205+
void MainWindow::cleanupCompressAliasEntries()
2206+
{
2207+
if (m_strCompressAliasRoot.isEmpty()) {
2208+
m_needCleanupCompressAlias = false;
2209+
return;
2210+
}
2211+
2212+
QDir aliasRoot(m_strCompressAliasRoot);
2213+
if (aliasRoot.exists()) {
2214+
aliasRoot.removeRecursively();
2215+
}
2216+
m_strCompressAliasRoot.clear();
2217+
m_needCleanupCompressAlias = false;
2218+
}
2219+
20822220
void MainWindow::showSuccessInfo(SuccessInfo eSuccessInfo, ErrorType eErrorType)
20832221
{
20842222
m_pSuccessPage->setSuccessType(eSuccessInfo);

src/source/mainwindow.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,18 @@ public :
214214
*/
215215
void ConstructAddOptionsByThread(const QString &path);
216216

217+
/**
218+
* @brief prepareCompressAliasEntries 为重命名文件准备临时别名文件
219+
* @param listEntry 待压缩的文件信息
220+
* @return 是否准备成功
221+
*/
222+
bool prepareCompressAliasEntries(QList<FileEntry> &listEntry);
223+
224+
/**
225+
* @brief cleanupCompressAliasEntries 清理临时别名文件
226+
*/
227+
void cleanupCompressAliasEntries();
228+
217229
/**
218230
* @brief showSuccessInfo 显示成功信息
219231
* @param eSuccessInfo 成功信息
@@ -575,6 +587,8 @@ private Q_SLOTS:
575587
#endif
576588

577589
QString m_strCurrentName;
590+
QString m_strCompressAliasRoot;
591+
bool m_needCleanupCompressAlias = false;
578592
};
579593

580594
class TitleWidget : public QWidget

0 commit comments

Comments
 (0)