|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2004 by ian reinhart geiser *
|
|
|
|
* geiseri@kde.org *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "specsupport.h"
|
|
|
|
#include "kdevproject.h"
|
|
|
|
#include "kdevmakefrontend.h"
|
|
|
|
#include "distpart_widget.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqerrormessage.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
//#include <tqvbox.h>
|
|
|
|
#include <tqgroupbox.h>
|
|
|
|
#include <tqtabwidget.h>
|
|
|
|
#include <tqmessagebox.h>
|
|
|
|
|
|
|
|
/// \FIXME This is at least the fifth place in the kdevelop code something like this exists
|
|
|
|
TQString QRegExp_escape(const TQString& str )
|
|
|
|
{
|
|
|
|
#if QT_VERSION >= 0x030100
|
|
|
|
return TQRegExp::escape(str);
|
|
|
|
#else
|
|
|
|
// this block is copyrighted by Trolltech AS (GPL)
|
|
|
|
static const char meta[] = "$()*+.?[\\]^{|}";
|
|
|
|
TQString quoted = str;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while ( i < (int) quoted.length() ) {
|
|
|
|
if ( strchr(meta, quoted[i].latin1()) != 0 )
|
|
|
|
quoted.insert( i++, "\\" );
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return quoted;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
SpecSupport::SpecSupport(DistpartPart *part) : packageBase(), m_part(part) {
|
|
|
|
dir = "";
|
|
|
|
|
|
|
|
// srcPackagePushButton = new TQPushButton(i18n("Src Package"),area());
|
|
|
|
// buildAllPushButton = new TQPushButton(i18n("Src/Binary Packages"),area());
|
|
|
|
// exportSPECPushButton = new TQPushButton(i18n("Export SPEC File"),area());
|
|
|
|
// importSPECPushButton = new TQPushButton(i18n("Import SPEC File"),area());
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// connect(buildAllPushButton, TQT_SIGNAL(clicked()),
|
|
|
|
// this, TQT_SLOT(slotbuildAllPushButtonPressed()));
|
|
|
|
// connect(exportSPECPushButton, TQT_SIGNAL(clicked()),
|
|
|
|
// this, TQT_SLOT(slotexportSPECPushButtonPressed()));
|
|
|
|
// connect(importSPECPushButton, TQT_SIGNAL(clicked()),
|
|
|
|
// this, TQT_SLOT(slotimportSPECPushButtonPressed()));
|
|
|
|
// connect(srcPackagePushButton, TQT_SIGNAL(clicked()),
|
|
|
|
// this, TQT_SLOT(slotsrcPackagePushButtonPressed()));
|
|
|
|
|
|
|
|
parseDotRpmmacros();
|
|
|
|
}
|
|
|
|
|
|
|
|
SpecSupport::~SpecSupport() {
|
|
|
|
}
|
|
|
|
|
|
|
|
// TQPushButton* buildAllPushButton;
|
|
|
|
void SpecSupport::slotbuildAllPushButtonPressed() {
|
|
|
|
TQMap<TQString,TQString>::Iterator it;
|
|
|
|
TQFile file1(dir + "/" + getAppSource());
|
|
|
|
TQFile file2(*(map.find("_sourcedir")) + "/" + getAppSource());
|
|
|
|
if (!file2.exists()) {
|
|
|
|
if (!file1.exists()) {
|
|
|
|
TQMessageBox::critical(0 ,i18n("Error"),i18n("You need to create a source archive first."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (KDevMakeFrontend *makeFrontend = m_part->extension<KDevMakeFrontend>("KDevelop/MakeFrontend"))
|
|
|
|
makeFrontend->queueCommand(dir,"cd " + KProcess::quote(dir) +
|
|
|
|
" && cp " + KProcess::quote(getAppSource()) + " " + KProcess::quote(*(map.find("_sourcedir"))));
|
|
|
|
}
|
|
|
|
if (KDevMakeFrontend *makeFrontend = m_part->extension<KDevMakeFrontend>("KDevelop/MakeFrontend"))
|
|
|
|
makeFrontend->queueCommand(dir,"cd " + KProcess::quote((((it = map.find("_specdir")) != map.end()) ? (*it) : dir)) +
|
|
|
|
" && rpmbuild -ba " + m_part->project()->projectName() + ".spec");
|
|
|
|
}
|
|
|
|
|
|
|
|
// TQPushButton* exportSPECPushButton;
|
|
|
|
void SpecSupport::slotexportSPECPushButtonPressed() {
|
|
|
|
TQMap<TQString,TQString>::Iterator it;
|
|
|
|
TQString specname = ((it = map.find("_specdir")) != map.end()) ? (*it) : (m_part->project()->projectDirectory());
|
|
|
|
specname += ("/" + m_part->project()->projectName() + ".spec");
|
|
|
|
TQFile file(specname);
|
|
|
|
|
|
|
|
if(file.open(IO_WriteOnly)) {
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
stream << generatePackage();
|
|
|
|
file.close();
|
|
|
|
} else {
|
|
|
|
kdDebug() << "TODO : intercept write error in SpecSupport::slotexportSPECPushButtonPressed()";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString SpecSupport::getInfo(TQString s, TQString motif) {
|
|
|
|
TQRegExp re(motif + "[ \t]*([^ \t].*[^ \t])[ \t]*");
|
|
|
|
if (re.exactMatch(s))
|
|
|
|
return re.cap(1);
|
|
|
|
return TQString::null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TQPushButton* importSPECPushButton;
|
|
|
|
void SpecSupport::slotimportSPECPushButtonPressed() {
|
|
|
|
TQString fileName = KFileDialog::getOpenFileName(dir,"*.spec");
|
|
|
|
if( fileName.isEmpty())
|
|
|
|
return;
|
|
|
|
TQFile file(fileName);
|
|
|
|
|
|
|
|
if(file.open(IO_ReadOnly)) {
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
TQString s = stream.readLine();
|
|
|
|
TQString info;
|
|
|
|
if (!(info = getInfo(s,"Name:")).isEmpty())
|
|
|
|
setAppName(info);
|
|
|
|
else if (!(info = getInfo(s,"Version:")).isEmpty())
|
|
|
|
setAppVersion(info);
|
|
|
|
else if (!(info = getInfo(s,"Release:")).isEmpty())
|
|
|
|
setAppRevision(info);
|
|
|
|
else if (!(info = getInfo(s,"Vendor:")).isEmpty())
|
|
|
|
setAppVendor(info);
|
|
|
|
else if (!(info = getInfo(s,"Copyright:")).isEmpty())
|
|
|
|
setAppLicense(info);
|
|
|
|
else if (!(info = getInfo(s,"Summary:")).isEmpty())
|
|
|
|
setAppSummary(info);
|
|
|
|
else if (!(info = getInfo(s,"Group:")).isEmpty())
|
|
|
|
setAppGroup(info);
|
|
|
|
else if (!(info = getInfo(s,"Packager:")).isEmpty())
|
|
|
|
setAppPackager(info);
|
|
|
|
else if (s.startsWith("%description")) {
|
|
|
|
TQString desc;
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
TQString str = stream.readLine();
|
|
|
|
if (str.startsWith("%")) break;
|
|
|
|
else desc += str + "\n";
|
|
|
|
}
|
|
|
|
setAppDescription(desc);
|
|
|
|
}
|
|
|
|
else if (s.startsWith("%changelog")) {
|
|
|
|
TQString change;
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
TQString str = stream.readLine();
|
|
|
|
if (str.startsWith("%")) break;
|
|
|
|
else change += str + "\n";
|
|
|
|
}
|
|
|
|
setAppChangelog(change);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpecSupport::slotAddFileButtonPressed(){
|
|
|
|
TQString filename = KFileDialog::getOpenFileName ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TQPushButton* srcPackagePushButton;
|
|
|
|
void SpecSupport::slotsrcPackagePushButtonPressed() {
|
|
|
|
TQMap<TQString,TQString>::Iterator it;
|
|
|
|
|
|
|
|
TQFile file1(dir + "/" + getAppSource());
|
|
|
|
TQFile file2(*(map.find("_sourcedir")) + "/" + getAppSource());
|
|
|
|
if (!file2.exists()) {
|
|
|
|
if (!file1.exists()) {
|
|
|
|
TQMessageBox::critical(0,i18n("Error"),i18n("You need to create a source archive first."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (KDevMakeFrontend *makeFrontend = m_part->extension<KDevMakeFrontend>("KDevelop/MakeFrontend"))
|
|
|
|
makeFrontend->queueCommand(dir,"cd " + KProcess::quote(dir) +
|
|
|
|
" && cp " + KProcess::quote(getAppSource()) + " " + KProcess::quote(*(map.find("_sourcedir"))));
|
|
|
|
}
|
|
|
|
if (KDevMakeFrontend *makeFrontend = m_part->extension<KDevMakeFrontend>("KDevelop/MakeFrontend"))
|
|
|
|
makeFrontend->queueCommand(dir,"cd " + KProcess::quote((((it = map.find("_specdir")) != map.end()) ? (*it) : dir)) +
|
|
|
|
" && rpmbuild -bs " + m_part->project()->projectName() + ".spec");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpecSupport::parseDotRpmmacros() {
|
|
|
|
TQFile dotfile(TQDir::homeDirPath() + "/.rpmmacros");
|
|
|
|
|
|
|
|
if (!dotfile.open(IO_ReadOnly)) {
|
|
|
|
// TQErrorMessage * msg = new TQErrorMessage(this);
|
|
|
|
// msg->message("It seems you don't have a ~/.rpmmacros\nYou may experience problems building packages.\n");
|
|
|
|
// msg->exec();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQTextStream stream(&dotfile);
|
|
|
|
|
|
|
|
// Perhaps will it appear as a necessity to parse the global rpm config file?
|
|
|
|
|
|
|
|
// Pre defined macros :
|
|
|
|
map.insert("name",getAppName());
|
|
|
|
|
|
|
|
// .rpmmacros parsing :
|
|
|
|
while (!stream.atEnd()) {
|
|
|
|
TQString s = stream.readLine();
|
|
|
|
TQRegExp re("%([^ \t]*)[ \t][ \t]*([^\t]*)$");
|
|
|
|
if(re.exactMatch(s)) {
|
|
|
|
TQRegExp subst("%\\{([^%]*)\\}");
|
|
|
|
TQString value = re.cap(2).stripWhiteSpace();
|
|
|
|
|
|
|
|
while(subst.search(value) != -1) {
|
|
|
|
value.replace(TQRegExp("%\\{"+ QRegExp_escape( subst.cap(1) ) +"\\}"),*map.find(subst.cap(1)));
|
|
|
|
}
|
|
|
|
map.insert(re.cap(1),value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dotfile.close();
|
|
|
|
|
|
|
|
// create directories if necessary :
|
|
|
|
createRpmDirectoryFromMacro("_topdir");
|
|
|
|
createRpmDirectoryFromMacro("_tmppath");
|
|
|
|
createRpmDirectoryFromMacro("_builddir");
|
|
|
|
createRpmDirectoryFromMacro("_rpmdir");
|
|
|
|
createRpmDirectoryFromMacro("_sourcedir");
|
|
|
|
createRpmDirectoryFromMacro("_specdir");
|
|
|
|
createRpmDirectoryFromMacro("_srcrpmdir");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SpecSupport::createRpmDirectoryFromMacro(const TQString & name) {
|
|
|
|
TQMap<TQString,TQString>::Iterator it;
|
|
|
|
if((it = map.find(name)) != map.end()) {
|
|
|
|
TQDir dir(*it);
|
|
|
|
if (!dir.exists()) return dir.mkdir(*it);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString SpecSupport::generatePackage( )
|
|
|
|
{
|
|
|
|
TQString spec;
|
|
|
|
spec += "# This spec file was generated by KDevelop \n";
|
|
|
|
spec += "# Please report any problem to KDevelop Team <kdevelop-devel@kdevelop.org> \n";
|
|
|
|
spec += "# Thanks to Matthias Saou for his explanations on http://freshrpms.net/docs/fight.html\n\n";
|
|
|
|
|
|
|
|
spec += "Name: " + getAppName() + "\n";
|
|
|
|
spec += "Version: " + getAppVersion() + "\n";
|
|
|
|
spec += "Release: " + getAppRevision() + "\n";
|
|
|
|
spec += "Vendor: " + getAppVendor() + "\n";
|
|
|
|
spec += "Copyright: " + getAppLicense() + "\n";
|
|
|
|
spec += "Summary: " + getAppSummary() + "\n";
|
|
|
|
spec += "Group: " + getAppGroup() + "\n";
|
|
|
|
spec += "Packager: " + getAppPackager() + "\n";
|
|
|
|
spec += "BuildRoot: %{_tmppath}/%{name}-root \n";
|
|
|
|
spec += "Source: " + getAppSource() + "\n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%description\n";
|
|
|
|
spec += getAppDescription()+ "\n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%prep\n";
|
|
|
|
spec += "%setup\n";
|
|
|
|
spec += "CFLAGS=\"$RPM_OPT_FLAGS\" CXXFLAGS=\"$RPM_OPT_FLAGS\" ./configure \\ \n";
|
|
|
|
spec += "--target=" + getAppArch() + "\n";
|
|
|
|
spec += "--disable-debug --enable-debug=no \n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%build\n";
|
|
|
|
spec += "%configure\n";
|
|
|
|
spec += "make\n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%install\n";
|
|
|
|
spec += "rm -rf %{buildroot}\n";
|
|
|
|
spec += "%makeinstall\n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%clean\n";
|
|
|
|
spec += "rm -rf %{buildroot}\n";
|
|
|
|
|
|
|
|
spec += "\n";
|
|
|
|
spec += "%post -p /sbin/ldconfig\n";
|
|
|
|
|
|
|
|
spec += "%postun -p /sbin/ldconfig\n";
|
|
|
|
|
|
|
|
spec += "%files\n";
|
|
|
|
spec += "%defattr(-, root, root)\n";
|
|
|
|
spec += "%doc AUTHORS COPYING ChangeLog NEWS README TODO\n";
|
|
|
|
spec += "%{_bindir}/*\n";
|
|
|
|
spec += "%{_libdir}/*.so.*\n";
|
|
|
|
spec += "%{_datadir}/%{name}\n";
|
|
|
|
spec += "%{_mandir}/man8/*\n";
|
|
|
|
|
|
|
|
spec += "%changelog\n";
|
|
|
|
spec += getAppChangelog() + "\n";
|
|
|
|
|
|
|
|
return spec;
|
|
|
|
}
|