2 ** Copyright (C) 1999,2000 Toivo Pedaste <toivo@ucs.uwa.edu.au>
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program in a file called COPYING; if not, write to
19 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 ** MA 02110-1301, USA.
24 ** Bug reports and questions can be sent to kde-devel@kde.org
27 #include <QtGui/QApplication>
28 #include <QtCore/QTextStream>
29 #include <QtCore/QSet>
30 #include <QtCore/QFile>
31 #include <QtCore/QDir>
36 #include <kiconloader.h>
37 #include <kactioncollection.h>
38 #include <kstandardaction.h>
40 #include <kmessagebox.h>
41 #include <kapplication.h>
45 #include "pkgInterface.h"
47 //////////////////////////////////////////////////////////////////////////////
48 //////////////////////////////////////////////////////////////////////////////
49 param::param(const QString
&nameP
, bool initP
, bool invertP
, const QString
&flagP
)
58 param::param(const QString
&nameP
, bool initP
, bool invertP
, const QString
&flagP
, const QString
&flagAP
)
72 //////////////////////////////////////////////////////////////////////////////
73 //////////////////////////////////////////////////////////////////////////////
74 pkgInterface::pkgInterface( ) : QObject(), new_pict(), updated_pict()
78 hasProgram
= ifExe("smart");
79 if (!hasProgram
&& hostName
.isEmpty()) {
80 KpMsg("Error",i18n("Kpackage requires the SMART Package Manager to be installed in order to function"), true);
81 exit(1); // exit the application
84 DELMSG
= i18n("'Delete this window to continue'");
86 folder
= SmallIcon("folder");
87 markInst
= UserIcon("tick");
88 markUnInst
= UserIcon("noball");
89 bad_pict
= UserIcon("dbad");
91 pFile
.setPattern("/([^/]*)\\s");
92 deb
.setPattern("(.+)_(.+)_.+\\.deb");
93 rpm
.setPattern("(.+)\\-(.+\\-.+)\\..+\\.rpm");
94 slack
.setPattern("(.+)\\-(.+\\-.+)\\-.+\\-\\.\\d+\\.tgz");
95 fin
.setPattern("^(.+)\\..+$");
97 queryMsg
= i18n("Querying SMART package list: ");
98 procMsg
= i18n("KPackage: Waiting on SMART");
100 packagePattern
= "*.deb *.rpm *.tgz";
106 hasSearchAll
= false;
109 //////////////////////////////////////////////////////////////////////////////
110 pkgInterface::~pkgInterface()
114 //////////////////////////////////////////////////////////////////////////////
116 void pkgInterface::makeMenu(KActionCollection
* act
)
118 updateM
= act
->addAction( "update");
119 updateM
->setText(i18n("&Update"));
120 updateM
->setIcon(KIcon("update"));
121 connect(updateM
, SIGNAL(triggered()), this, SLOT(updateS()));
123 upgradeM
= act
->addAction( "upgrade");
124 upgradeM
->setText(i18n("U&pgrade"));
125 upgradeM
->setIcon(KIcon("upgrade"));
126 connect(upgradeM
, SIGNAL(triggered()), this, SLOT(upgradeS()));
128 fixupM
= act
->addAction( "fixup" );
129 fixupM
->setText(i18n("&Fixup"));
130 connect(fixupM
, SIGNAL(triggered()), this, SLOT(fixupS()));
133 void pkgInterface::setMenu(KActionCollection
*, bool enable
)
135 updateM
->setEnabled(enable
);
136 upgradeM
->setEnabled(enable
);
137 fixupM
->setEnabled(enable
);
140 //////////////////////////////////////////////////////////////////////////////
141 bool pkgInterface::parseName(const QString
&name
, QString
*n
, QString
*v
) {
144 if (deb
.indexIn(name
) >= 0) {
148 if (rpm
.indexIn(name
) >= 0) {
152 if (slack
.indexIn(name
) >= 0) {
156 if (fin
.indexIn(name
) >= 0) {
163 // kDebug() << "n=" << *n << " v=" << *v << "\n";
167 QStringList
pkgInterface::depends(const QString
&, int ) {return QStringList();}
169 bool pkgInterface::ifExe(QString exe
) {
170 if (!KGlobal::dirs()->findExe( exe
).isNull()) {
173 kDebug() << "Program not found: " << exe
<< "\n";
179 void pkgInterface::smerge(packageInfo
*)
182 packageInfo
*pkgInterface::collectPath(const QString
&name
)
184 int p
= name
.lastIndexOf("/");
186 QString dir
= name
.left( p
);
187 QString fname
= name
.mid(p
+ 1);
188 // kDebug() << "F=" << fname << " D=" << dir << "\n";
189 return collectDir(fname
,"",dir
);
191 return collectDir(name
,"","");
195 packageInfo
*pkgInterface::collectDir(const QString
&name
, const QString
&size
, const QString
&dir
)
197 kDebug() << "collectDir " << name
<< " " << size
<< " " << dir
<< "\n";
200 if (parseName(name
, &n
, &v
)) {
201 QMap
<QString
, QString
> a
;
203 a
.insert("group", "NEW");
205 a
.insert("version", v
);
206 a
.insert("file-size", size
);
207 a
.insert("filename", name
);
208 a
.insert("base", dir
);
210 packageInfo
*i
= new packageInfo(a
,this);
211 i
->packageState
= packageInfo::AVAILABLE
;
220 //////////////////////////////////////////////////////////////////////////////
222 QString
pkgInterface::provMap(const QString
&p
)
224 // kDebug() << "provMap=>" << p;
227 /////////////////////////////////////////////////////////////////////////////
229 QString
pkgInterface::getDelimiter(short ptype
)
238 //////////////////////////////////////////////////////////////////////////////
239 packageInfo
*pkgInterface::collectInfo(QStringList
&ln
, pkgInterface
*pkgInt
)
241 QMap
<QString
, QString
> a
;
244 bool bad_install
= false;
245 bool haveName
= false;
246 short pType
= lastType
;
248 QRegExp
isDeb("\\.deb\\s");
249 QRegExp
isRpm("\\.deb\\s");
250 QRegExp
isSlack("\\.tgz\\s");
252 for (int i
= 0; i
< ln
.size(); ++i
) {
255 int col
= (ln
[i
]).indexOf(':');
256 key
= ((ln
[i
]).left(col
)).toLower();
260 val
= (ln
[i
]).mid(col
+2);
261 // kDebug() << key << "," << val << "\n";
262 if (key
== "name" || key
== "package") {
263 a
.insert("name", val
);
265 } else if (key
== "summary") {
266 a
.insert("summary", val
);
267 } else if (key
== "description") {
268 if (!a
.contains("summary")) {
269 a
.insert("summary",val
);
272 while (++i
< ln
.size()) {
273 (ln
[i
]).replace(QRegExp("<"),"<");
274 (ln
[i
]).replace(QRegExp(">"),">");
275 if ((ln
[i
])[0] == ' ') {
276 if ((ln
[i
])[1] == '*') {
277 ln
[i
] = "<br>" + ln
[i
];
278 } else if ((ln
[i
])[1] == '.') {
283 a
.insert("description", desc
);
287 a
.insert("description", desc
);
289 } else if (key
== "section") {
290 a
.insert("group", val
);
291 } else if (key
== "priority") {
293 a
.insert("priority", val
);
295 } else if (key
== "reference urls") {
296 if (!val
.isEmpty()) {
297 a
.insert("reference urls", val
);
299 } else if (key
== "flags") {
300 if (!val
.isEmpty()) {
301 a
.insert("flags", val
);
303 } else if (key
== "version") {
304 a
.insert("version", val
);
305 } else if (key
== "installed size") {
306 a
.insert("size", val
);
307 } else if (key
== "installed-size") {
308 a
.insert("size", val
);
309 } else if (key
== "channels") {
310 a
.insert("channels", val
);
311 if (val
.contains("DEB")) {
313 } else if (val
.contains("RPM")) {
315 } else if (val
.contains("SLACK")) {
318 } else if (key
== "urls") {
321 while (++i
< ln
.size()) {
322 // kDebug() << "id=" << i << " s= " << ln.size() << " " << ln[i] << "\n";
323 if (isDeb
.indexIn(ln
[i
]) >= 0) {
325 } else if (isRpm
.indexIn(ln
[i
]) >= 0) {
327 pkgInt
= kpinterface
[RPMt
];
328 } else if (isSlack
.indexIn(ln
[i
]) >= 0) {
335 // kDebug() << "C=" << key << "," << val <<"\n";
338 QString packName
= a
["name"] + getDelimiter(pType
) + a
["version"];
339 // kdDebug() << "CI " << packName << " " << pType << " C=" << kpackage->management->isInstalled.contains(packName) << " " << lastType << "\n";
343 pkgInt
= kpinterface
[DEBt
];
344 } else if (pType
== RPMt
) {
345 pkgInt
= kpinterface
[RPMt
];
346 } else if (!pkgInt
) {
351 packageInfo
*i
= new packageInfo(a
,pkgInt
);
353 i
->packageState
= packageInfo::BAD_INSTALL
;
354 } else if (!kpackage
->management
->isInstalled
.contains(packName
)) {
355 i
->packageState
= packageInfo::AVAILABLE
;
356 // kDebug() << " A=" << i->packageState << " [" << packName << "]\n";
358 i
->packageState
= packageInfo::INSTALLED
;
359 // kDebug() << " I=" << i->packageState << " [" << packName << "]\n";
363 // kDebug() << "==" << packName << "\n";
370 //////////////////////////////////////////////////////////////////////////////
371 void pkgInterface::removeLastEmpty(QStringList
&list
)
373 if (list
.count() > 0) {
374 QMutableListIterator
<QString
> i(list
);
376 if (i
.peekPrevious().isEmpty()) {
380 if (i
.peekPrevious().isEmpty()) {
385 // kDebug() << "R1" << list <<"\n";
388 QStringList
pkgInterface::listInstalls(const QStringList
&packs
, bool install
, bool &)
390 kDebug() << "pkgInterface::listInstalls\n";
391 // Get list of dependencies
396 s
= "smart install --dump-noversion ";
398 s
= "smart remove --dump-noversion ";
401 foreach (const QString
&pk
, packs
) {
406 QStringList list
= kpty
->run(s
, true);
407 // kDebug() << "L=" << list << "\n";
410 removeLastEmpty(list
);
411 QMutableListIterator
<QString
> i(list
);
413 // kDebug() << "L2=" << list << "\n";
415 // Skip non-blank lines (wanted text)
416 while (i
.hasPrevious()) {
417 if (!i
.peekPrevious().isEmpty() && !i
.peekPrevious().contains(' ')) {
425 while (i
.hasPrevious()) {
429 // kDebug() << "L3=" << list << "\n";
433 return QStringList();
437 //////////////////////////////////////////////////////////////////////////////
439 QStringList
pkgInterface::getPackageState( const QStringList
&packages
)
441 kDebug() << "pkgInterface::getPackageState\n";
442 // Get state of packages
444 QApplication::setOverrideCursor( Qt::WaitCursor
);
445 kpackage
->setStatus(i18n("Querying package state"));
449 s
= "smart query --installed ";
451 foreach (const QString
&n
, packages
) {
455 QStringList list
= kpty
->run(s
);
456 // kDebug() << "s=" << s << "LS=" << list.count() << "\n";
457 // kDebug() << "Status=" << list << "\n";
459 removeLastEmpty(list
);
461 QMutableListIterator
<QString
> i(list
);
465 // Remove non-blank lines forward (cache access info)
466 while (i
.hasNext()) {
467 if (!i
.peekNext().isEmpty()) {
475 // Remove blank lines forward (cache access info)
476 while (i
.hasNext()) {
477 if (i
.peekNext().isEmpty()) {
485 // kDebug() << "Status=" << list << "\n";
486 QApplication::restoreOverrideCursor();
490 void pkgInterface::getPackageDepends(packageInfo
*p
)
492 // Get state of packages
494 QApplication::setOverrideCursor( Qt::WaitCursor
);
495 kpackage
->setStatus(i18n("Querying package dependencies"));
499 s
= "smart query --show-requires --show-provides --show-requiredby ";
501 s
+= p
->getInfo("name") + getDelimiter(p
->packType
) + p
->getInfo("version");
503 QStringList list
= kpty
->run(s
);
504 // kDebug() << "s=" << s << "LS=" << list.count() << "\n";
505 // kDebug() << "Status=" << list << "\n";
507 removeLastEmpty(list
);
509 QMutableListIterator
<QString
> i(list
);
512 // Remove non-blank lines forward (cache access info)
513 while (i
.hasNext()) {
514 if (!i
.peekNext().isEmpty()) {
522 // Remove blank lines forward (cache access info)
523 while (i
.hasNext()) {
524 if (i
.peekNext().isEmpty()) {
532 // kDebug() << "Status=" << list << "\n";
533 p
->depends
= new QStringList(list
);
534 QApplication::restoreOverrideCursor();
537 ///////////////////////////////////////////////////////////////
539 void pkgInterface::listPackages(QList
<packageInfo
*> &pki
)
541 listInstalledPackages(pki
);
542 if (hostName
.isEmpty()) {
543 listPackagesFile(pki
);
545 listRemotePackages(pki
);
549 void pkgInterface::listInstalledPackages(QList
<packageInfo
*> &)
551 // Get list of installed packages
554 kpackage
->setStatus(i18n("Querying installed package list"));
556 QString cmd
= "smart query --installed";
558 QStringList list
= kpty
->run(cmd
);
559 // kDebug() << "s=" << cmd << "LS=" << list.count() << "\n";
560 // kDebug() << "Status=" << list << "\n";
563 if (kpty
->Result
== 127) { // smart command not found
564 QApplication::restoreOverrideCursor();
565 QString sm
= i18n("'smart' package manager is required");
566 if (list
.count() == 0) {
569 KMessageBox::detailedSorry(kpkg
,sm
,list
[0]);
571 kpackage
->fileQuit();
572 } else if (kpty
->Result
== 1) { // smart not initialised
573 list
= kpty
->run(cmd
,true,true);
574 kpackage
->displayMsg
= i18n("Press 'Update' to display available packages ");
577 if (list
.count() > 0) {
581 for ( QStringList::const_iterator it
= list
.constBegin(); it
!= list
.constEnd(); ++it
) {
582 kpackage
->management
->isInstalled
.insert(*it
);
586 QMutableListIterator
<QString
> i(list
);
588 // Remove non-blank lines forward (cache access info)
589 while (i
.hasNext()) {
590 if (!i
.peekNext().isEmpty()) {
599 void pkgInterface::listPackagesFile(QList
<packageInfo
*> &pki
)
601 QApplication::setOverrideCursor( Qt::WaitCursor
);
602 kpackage
->setStatus(i18n("Generating package information"));
604 QString tempFile
= KStandardDirs::locateLocal("tmp","smart.list");
606 QString cmd
= "/bin/sh -c 'smart info --urls >" + tempFile
+ "'"; //krazy:exclude=duoblequote_chars
607 QStringList list
= kpty
->run(cmd
);
609 kpackage
->setStatus(i18n("Processing package information"));
612 QFile
file( tempFile
);
613 if ( file
.open( QIODevice::ReadOnly
) ) {
614 QTextStream
stream( &file
);
616 while ( !stream
.atEnd() ) {
617 line
= stream
.readLine(); // line of text excluding '\n'
618 if (!line
.isEmpty()) {
619 // kDebug() << line << "\n";
622 // kDebug() << line << "-----------------------------\n";
624 p
= collectInfo(lines
);
626 if (!p
->pkgInsert(pki
, p
->packageState
== packageInfo::INSTALLED
)) {
636 kpackage
->setStatus("");
637 QApplication::restoreOverrideCursor();
641 void pkgInterface::listRemotePackages(QList
<packageInfo
*> &)
645 kDebug() << "pkgInterface::listRemotePackages\n";
649 kpackage
->setStatus(i18n("Querying SMART package list: %1", hostName
));
650 kpackage
->setPercent(20);
653 connect(kpty
, SIGNAL(textLine(const QString
&)), this,
654 SLOT(textIn(const QString
&)));
657 QString cmd
= "smart info --urls | cat";
658 // QString cmd = "cat /home/toivo/s.info";
660 QStringList list
= kpty
->run(cmd
);
661 kpackage
->setStatus(i18n("Processing SMART package list: %1", hostName
));
662 // kDebug() << "P=" << list.count() <<"\n";
664 disconnect(kpty
, SIGNAL(textLine(const QString
&)), this,
665 SLOT(textIn(const QString
&)));
668 kpackage
->setStatus(i18n("SMART"));
669 kpackage
->setPercent(100);
672 void pkgInterface::textIn(const QString
&s
)
677 // kDebug() << " textIn=[" << ss << "]\n";
682 // kDebug() << "===" << packList << "\n";
684 if (pCnt
% 250 == 0) {
685 kpackage
->setPercent(20 + (pCnt
* 80) / PMAX
);
688 p
= collectInfo(packList
);
690 if (!p
->pkgInsert(kpackage
->management
->allPackages
, p
->packageState
== packageInfo::INSTALLED
)) {
702 /////////////////////////////////////////////////////////////////////////////
704 void pkgInterface::getFileList(packageInfo
*p
)
706 if (p
->packageState
== packageInfo::INSTALLED
) {
709 if (!p
->getFilename().isEmpty()) {
716 void pkgInterface::getIFileList(packageInfo
*p
)
718 QApplication::setOverrideCursor( Qt::WaitCursor
);
719 QString pn
= "smart info --paths " + p
->getInfo("name") + getDelimiter(p
->packType
) + p
->getInfo("version");
722 QStringList res
= kpty
->run(pn
);
723 // kDebug() << "Status1=" << res << "\n";
725 QMutableListIterator
<QString
> i(res
);
728 // remove blank lines
729 while (i
.hasPrevious()) {
730 if (i
.peekPrevious().isEmpty()) {
738 // Skip lines starting with space
739 while (i
.hasPrevious()) {
740 if (i
.peekPrevious().left(1) == " ") {
741 i
.previous().remove(0,1);
749 while (i
.hasPrevious()) {
754 p
->files
= new QStringList(res
);
755 QApplication::restoreOverrideCursor();
756 // kDebug() << "Status=" << res << "\n";
759 //////////////////////////////////////////////////////////////////////////////
760 QStringList
pkgInterface::verify(packageInfo
*, const QStringList
&files
)
764 QStringList errorlist
;
767 if (hostName
.isEmpty()) {
769 uint step
= (files
.count() / 100) + 1;
771 kpackage
->setStatus(i18n("Verifying"));
772 kpackage
->setPercent(0);
774 for( QStringList::ConstIterator it
= files
.begin();
778 // Update the status progress
782 kpackage
->setPercent(p
);
785 if (!d
.exists(*it
)) {
786 errorlist
.append(*it
);
790 kpackage
->setPercent(100);
795 //////////////////////////////////////////////////////////////////////////////
796 //////////////////////////////////////////////////////////////////////////////
798 QString
pkgInterface::install(int installFlags
, QList
<packageInfo
*> p
, bool &test
)
802 foreach (packageInfo
*i
, p
) {
803 QString fname
= i
->fetchFilename();
804 if (!fname
.isEmpty()) {
809 return doInstall(installFlags
, packs
, test
);
813 QString
pkgInterface::install(int installFlags
, packageInfo
*p
, bool &test
)
815 QString fname
= p
->fetchFilename();
817 return doInstall(installFlags
, fname
, test
);
822 QString
pkgInterface::doInstall(int installFlags
, const QString
&packs
, bool &test
)
824 QString s
= env
+ "smart install -y ";
825 // QString s = env + "dpkg -i ";
826 s
+= setOptions(installFlags
, paramsInst
);
829 kDebug() << "iCMD=" << s
<< "\n";
831 if ((installFlags
>>0 & 1) || (installFlags
>>5 & 1))
837 //////////////////////////////////////////////////////////////////////////////
839 QString
pkgInterface::uninstall(int uninstallFlags
, QList
<packageInfo
*> p
, bool &test
)
843 // for (i = p->first(); i!= 0; i = p->next()) {
844 foreach (packageInfo
*i
, p
) {
845 packs
+= i
->getInfo("name");
848 return doUninstall( uninstallFlags
, packs
, test
);
851 QString
pkgInterface::uninstall(int uninstallFlags
, packageInfo
*p
, bool &test
)
853 QString
packs( p
->getInfo("name"));
855 return doUninstall(uninstallFlags
, packs
, test
);
858 QString
pkgInterface::doUninstall(int uninstallFlags
, const QString
&packs
, bool &test
)
860 QString s
= env
+ "smart remove -y ";
861 s
+= setOptions(uninstallFlags
, paramsUninst
);
864 kDebug() << "uCMD=" << s
<< "\n";
866 if (uninstallFlags
>>2 & 1)
872 //////////////////////////////////////////////////////////////////////////////
874 void pkgInterface::updateS()
876 if (kprun
->run("smart update", "SMART update")) {
878 kpackage
->management
->collectData(true);
882 void pkgInterface::upgradeS()
884 if (kprun
->run(env
+ "smart upgrade -y", "SMART upgrade")) {
886 kpackage
->management
->collectData(true);
890 void pkgInterface::fixupS()
892 if (kprun
->run(env
+ "smart fix -y", "SMART fix")) {
894 kpackage
->management
->collectData(true);
899 //////////////////////////////////////////////////////////////////////////////
901 bool pkgInterface::depTab(packageInfo
*p
) {
902 if (p
->packageState
== packageInfo::INSTALLED
) {
908 QString
pkgInterface::setOptions(int flags
, QList
<param
*> ¶ms
)
914 // for ( p=params.first(); p != 0; p=params.next(), i++ ) {
915 foreach (param
*p
, params
) {
916 if ((flags
>>i
& 1) ^ p
->invert
) {
919 if (!p
->flagA
.isEmpty())
927 ///////////////////////////////////////////////////////////////////////////////////
929 packageInfo
*pkgInterface::getPackageInfo(const QString
&) {
933 void pkgInterface::getFFileList(packageInfo
*) {
936 QStringList
pkgInterface::FindFile(const QString
&, bool ) {
941 QStringList
pkgInterface::getChangeLog(packageInfo
*) {
946 bool pkgInterface::filesTab(packageInfo
*) {
950 bool pkgInterface::changeTab(packageInfo
*) {
954 packageInfo
*pkgInterface::getFPackageInfo(const QString
&) {
961 #include "pkgInterface.moc"