forked from qt-creator/qt-creator
RemoteLinux: Improve handling of symbolic links when deploying.
We used to follow the links, resulting in unnecessary traffic. Now we just recreate the links. Note: This requires the user to not have dependencies that resolve to something outside the set of files to deploy. Change-Id: I3f439739115b4d07b36a71fe2041d8725a25abfd Reviewed-on: http://codereview.qt.nokia.com/1582 Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
This commit is contained in:
@@ -64,6 +64,9 @@ public:
|
|||||||
quint32 requestId);
|
quint32 requestId);
|
||||||
SftpOutgoingPacket &generateWriteFile(const QByteArray &handle,
|
SftpOutgoingPacket &generateWriteFile(const QByteArray &handle,
|
||||||
quint64 offset, const QByteArray &data, quint32 requestId);
|
quint64 offset, const QByteArray &data, quint32 requestId);
|
||||||
|
|
||||||
|
// Note: OpenSSH's SFTP server has a bug that reverses the filePath and target
|
||||||
|
// arguments, so this operation is not portable.
|
||||||
SftpOutgoingPacket &generateCreateLink(const QString &filePath, const QString &target,
|
SftpOutgoingPacket &generateCreateLink(const QString &filePath, const QString &target,
|
||||||
quint32 requestId);
|
quint32 requestId);
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public:
|
|||||||
QList<DeployableFile> filesToUpload;
|
QList<DeployableFile> filesToUpload;
|
||||||
SftpChannel::Ptr uploader;
|
SftpChannel::Ptr uploader;
|
||||||
SshRemoteProcess::Ptr mkdirProc;
|
SshRemoteProcess::Ptr mkdirProc;
|
||||||
|
SshRemoteProcess::Ptr lnProc;
|
||||||
QList<DeployableFile> deployableFiles;
|
QList<DeployableFile> deployableFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,6 +162,28 @@ void GenericDirectUploadService::handleUploadFinished(Utils::SftpJobId jobId, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericDirectUploadService::handleLnFinished(int exitStatus)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_d->state == Uploading, setFinished(); return);
|
||||||
|
|
||||||
|
if (m_d->stopRequested) {
|
||||||
|
setFinished();
|
||||||
|
handleDeploymentDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeployableFile d = m_d->filesToUpload.takeFirst();
|
||||||
|
const QString nativePath = QDir::toNativeSeparators(d.localFilePath);
|
||||||
|
if (exitStatus != SshRemoteProcess::ExitedNormally || m_d->lnProc->exitCode() != 0) {
|
||||||
|
emit errorMessage(tr("Failed to upload file '%1'.").arg(nativePath));
|
||||||
|
setFinished();
|
||||||
|
handleDeploymentDone();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
saveDeploymentTimeStamp(d);
|
||||||
|
uploadNextFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GenericDirectUploadService::handleMkdirFinished(int exitStatus)
|
void GenericDirectUploadService::handleMkdirFinished(int exitStatus)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_d->state == Uploading, setFinished(); return);
|
QTC_ASSERT(m_d->state == Uploading, setFinished(); return);
|
||||||
@@ -182,18 +205,43 @@ void GenericDirectUploadService::handleMkdirFinished(int exitStatus)
|
|||||||
m_d->filesToUpload.removeFirst();
|
m_d->filesToUpload.removeFirst();
|
||||||
uploadNextFile();
|
uploadNextFile();
|
||||||
} else {
|
} else {
|
||||||
const SftpJobId job = m_d->uploader->uploadFile(d.localFilePath,
|
const QString remoteFilePath = d.remoteDir + QLatin1Char('/') + fi.fileName();
|
||||||
d.remoteDir + QLatin1Char('/') + fi.fileName(),
|
if (fi.isSymLink()) {
|
||||||
SftpOverwriteExisting);
|
const QString target = fi.dir().relativeFilePath(fi.symLinkTarget()); // see QTBUG-5817.
|
||||||
if (job == SftpInvalidJob) {
|
const QString command = QLatin1String("ln -vsf ") + target + QLatin1Char(' ')
|
||||||
emit errorMessage(tr("Failed to upload file '%1': "
|
+ remoteFilePath;
|
||||||
"Could not open for reading.").arg(nativePath));
|
|
||||||
setFinished();
|
// See comment in SftpChannel::createLink as to why we can't use it.
|
||||||
handleDeploymentDone();
|
m_d->lnProc = connection()->createRemoteProcess(command.toUtf8());
|
||||||
|
connect(m_d->lnProc.data(), SIGNAL(closed(int)), SLOT(handleLnFinished(int)));
|
||||||
|
connect(m_d->lnProc.data(), SIGNAL(outputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdOutData(QByteArray)));
|
||||||
|
connect(m_d->lnProc.data(), SIGNAL(errorOutputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdErrData(QByteArray)));
|
||||||
|
m_d->lnProc->start();
|
||||||
|
} else {
|
||||||
|
const SftpJobId job = m_d->uploader->uploadFile(d.localFilePath, remoteFilePath,
|
||||||
|
SftpOverwriteExisting);
|
||||||
|
if (job == SftpInvalidJob) {
|
||||||
|
emit errorMessage(tr("Failed to upload file '%1': "
|
||||||
|
"Could not open for reading.").arg(nativePath));
|
||||||
|
setFinished();
|
||||||
|
handleDeploymentDone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericDirectUploadService::handleStdOutData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
emit stdOutData(QString::fromUtf8(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenericDirectUploadService::handleStdErrData(const QByteArray &data)
|
||||||
|
{
|
||||||
|
emit stdErrData(QString::fromUtf8(data));
|
||||||
|
}
|
||||||
|
|
||||||
void GenericDirectUploadService::stopDeployment()
|
void GenericDirectUploadService::stopDeployment()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_d->state == InitializingSftp || m_d->state == Uploading, setFinished(); return);
|
QTC_ASSERT(m_d->state == InitializingSftp || m_d->state == Uploading, setFinished(); return);
|
||||||
@@ -226,9 +274,10 @@ void GenericDirectUploadService::setFinished()
|
|||||||
{
|
{
|
||||||
m_d->stopRequested = false;
|
m_d->stopRequested = false;
|
||||||
m_d->state = Inactive;
|
m_d->state = Inactive;
|
||||||
if (m_d->mkdirProc) {
|
if (m_d->mkdirProc)
|
||||||
disconnect(m_d->mkdirProc.data(), 0, this, 0);
|
disconnect(m_d->mkdirProc.data(), 0, this, 0);
|
||||||
}
|
if (m_d->lnProc)
|
||||||
|
disconnect(m_d->lnProc.data(), 0, this, 0);
|
||||||
if (m_d->uploader) {
|
if (m_d->uploader) {
|
||||||
disconnect(m_d->uploader.data(), 0, this, 0);
|
disconnect(m_d->uploader.data(), 0, this, 0);
|
||||||
m_d->uploader->closeChannel();
|
m_d->uploader->closeChannel();
|
||||||
@@ -249,10 +298,13 @@ void GenericDirectUploadService::uploadNextFile()
|
|||||||
QFileInfo fi(d.localFilePath);
|
QFileInfo fi(d.localFilePath);
|
||||||
if (fi.isDir())
|
if (fi.isDir())
|
||||||
dirToCreate += QLatin1Char('/') + fi.fileName();
|
dirToCreate += QLatin1Char('/') + fi.fileName();
|
||||||
const QByteArray command = "mkdir -p " + dirToCreate.toUtf8();
|
const QString command = QLatin1String("mkdir -vp ") + dirToCreate;
|
||||||
m_d->mkdirProc = connection()->createRemoteProcess(command);
|
m_d->mkdirProc = connection()->createRemoteProcess(command.toUtf8());
|
||||||
connect(m_d->mkdirProc.data(), SIGNAL(closed(int)), SLOT(handleMkdirFinished(int)));
|
connect(m_d->mkdirProc.data(), SIGNAL(closed(int)), SLOT(handleMkdirFinished(int)));
|
||||||
// TODO: Connect stderr.
|
connect(m_d->mkdirProc.data(), SIGNAL(outputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdOutData(QByteArray)));
|
||||||
|
connect(m_d->mkdirProc.data(), SIGNAL(errorOutputAvailable(QByteArray)),
|
||||||
|
SLOT(handleStdErrData(QByteArray)));
|
||||||
emit progressMessage(tr("Uploading file '%1'...")
|
emit progressMessage(tr("Uploading file '%1'...")
|
||||||
.arg(QDir::toNativeSeparators(d.localFilePath)));
|
.arg(QDir::toNativeSeparators(d.localFilePath)));
|
||||||
m_d->mkdirProc->start();
|
m_d->mkdirProc->start();
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ private slots:
|
|||||||
void handleSftpInitializationFailed(const QString &errorMessage);
|
void handleSftpInitializationFailed(const QString &errorMessage);
|
||||||
void handleUploadFinished(Utils::SftpJobId jobId, const QString &errorMsg);
|
void handleUploadFinished(Utils::SftpJobId jobId, const QString &errorMsg);
|
||||||
void handleMkdirFinished(int exitStatus);
|
void handleMkdirFinished(int exitStatus);
|
||||||
|
void handleLnFinished(int exitStatus);
|
||||||
|
void handleStdOutData(const QByteArray &data);
|
||||||
|
void handleStdErrData(const QByteArray &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isDeploymentNecessary() const;
|
bool isDeploymentNecessary() const;
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ void MaemoRemoteCopyFacility::copyNextFile()
|
|||||||
sourceFilePath += d.localFilePath;
|
sourceFilePath += d.localFilePath;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QString command = QString::fromLatin1("%1 mkdir -p %3 && %1 cp -r %2 %3")
|
QString command = QString::fromLatin1("%1 mkdir -p %3 && %1 cp -a %2 %3")
|
||||||
.arg(MaemoGlobal::remoteSudo(m_devConf->osType(),
|
.arg(MaemoGlobal::remoteSudo(m_devConf->osType(),
|
||||||
m_copyRunner->connection()->connectionParameters().userName),
|
m_copyRunner->connection()->connectionParameters().userName),
|
||||||
sourceFilePath, d.remoteDir);
|
sourceFilePath, d.remoteDir);
|
||||||
|
|||||||
Reference in New Issue
Block a user