Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

package related stuff

- libpkg
- y2client/packager
- y2m_inst/ycp/packages

svn path=/trunk/packager/; revision=2893
  • Loading branch information...
commit 62549b238abef1935721fab02354ca4c4247b2b4 1 parent c3d61d5
@kkaempf kkaempf authored
Showing with 363,101 additions and 0 deletions.
  1. +21 −0 .cvsignore
  2. +1 −0  MAINTAINER
  3. +16 −0 Makefile.cvs
  4. +1 −0  RPMNAME
  5. +1 −0  VERSION
  6. +8 −0 client-packager/.cvsignore
  7. +5 −0 client-packager/Makefile.am
  8. +3 −0  client-packager/doc/.cvsignore
  9. +5 −0 client-packager/doc/Makefile.am
  10. +3 −0  client-packager/doc/autodocs/.cvsignore
  11. +19 −0 client-packager/doc/autodocs/Makefile.am
  12. +9 −0 client-packager/src/.cvsignore
  13. +12 −0 client-packager/src/Makefile.am
  14. +547 −0 client-packager/src/Rpm_Installer.cc
  15. +149 −0 client-packager/src/Rpm_Installer.h
  16. +5 −0 client-packager/src/Y2CCPackager.cc
  17. +27 −0 client-packager/src/Y2CCPackager.h
  18. +381 −0 client-packager/src/Y2PackagerComponent.cc
  19. +92 −0 client-packager/src/Y2PackagerComponent.h
  20. +8 −0 client-packager/testsuite/.cvsignore
  21. +21 −0 client-packager/testsuite/Makefile.am
  22. 0  client-packager/testsuite/y2packager.cc
  23. +15 −0 configure.in.in
  24. +1,481 −0 doc/PackageManagement.xml
  25. +93 −0 doc/block_diagram.fig
  26. BIN  doc/block_diagram.png
  27. +21 −0 libpkg/.cvsignore
  28. +3 −0  libpkg/Makefile.am
  29. +2 −0  libpkg/doc/.cvsignore
  30. +9 −0 libpkg/doc/Makefile.am
  31. +3 −0  libpkg/doc/autodocs/.cvsignore
  32. +18 −0 libpkg/doc/autodocs/Makefile.am
  33. +7 −0 libpkg/src/.cvsignore
  34. +466 −0 libpkg/src/ConfigFile.cc
  35. +20 −0 libpkg/src/Makefile.am
  36. +101 −0 libpkg/src/Package.cc
  37. +86 −0 libpkg/src/PackageKey.cc
  38. +156 −0 libpkg/src/PathInfo.cc
  39. +150 −0 libpkg/src/PathInfo.h
  40. +294 −0 libpkg/src/Pathname.cc
  41. +124 −0 libpkg/src/Pathname.h
  42. +97 −0 libpkg/src/RawPackage.cc
  43. +134 −0 libpkg/src/RawPackage.h
  44. +3,324 −0 libpkg/src/RawPackageInfo.cc
  45. +2,148 −0 libpkg/src/Solver.cc
  46. +463 −0 libpkg/src/TagParser.cc
  47. +144 −0 libpkg/src/TagParser.h
  48. +219 −0 libpkg/src/TagSets.h
  49. +268 −0 libpkg/src/Version.cc
  50. +102 −0 libpkg/src/Version.h
  51. +3 −0  libpkg/src/include/.cvsignore
  52. +34 −0 libpkg/src/include/Makefile.am
  53. +31 −0 libpkg/src/include/PKG.h
  54. +2 −0  libpkg/src/include/pkg/.cvsignore
  55. +132 −0 libpkg/src/include/pkg/ConfigFile.h
  56. +31 −0 libpkg/src/include/pkg/Makefile.am
  57. +118 −0 libpkg/src/include/pkg/Package.h
  58. +80 −0 libpkg/src/include/pkg/PackageKey.h
  59. +408 −0 libpkg/src/include/pkg/RawPackageInfo.h
  60. +427 −0 libpkg/src/include/pkg/Solver.h
  61. +277 −0 libpkg/src/include/pkg/pkginfo.h
  62. +11 −0 libpkg/testsuite/.cvsignore
  63. +17 −0 libpkg/testsuite/Makefile.am
  64. +16 −0 libpkg/testsuite/README
  65. +56 −0 libpkg/testsuite/runpkg.cc
  66. +54 −0 libpkg/testsuite/runscr.cc
  67. +2 −0  packages/.cvsignore
  68. +1 −0  packages/MAINTAINER
  69. +15 −0 packages/Makefile.am
  70. +2 −0  packages/agents/.cvsignore
  71. +12 −0 packages/agents/Makefile.am
  72. +67 −0 packages/agents/ag_instsource
  73. +31 −0 packages/agents/yast2_instsource.scr
  74. +471 −0 packages/doc/YaST2_package.html
  75. BIN  packages/doc/add_needed.png
  76. BIN  packages/doc/add_pkg.png
  77. BIN  packages/doc/auto_conflict.png
  78. BIN  packages/doc/check_again.png
  79. BIN  packages/doc/exist_conflict.png
  80. BIN  packages/doc/exit_wrn.png
  81. BIN  packages/doc/inst_conflict.png
  82. BIN  packages/doc/new_conflict.png
  83. BIN  packages/doc/new_conflict2.png
  84. BIN  packages/doc/nfs_conflict.png
  85. BIN  packages/doc/ok.png
  86. BIN  packages/doc/overview_installed.png
  87. BIN  packages/doc/overview_new_inst.png
  88. BIN  packages/doc/search.png
  89. BIN  packages/doc/search_result.png
  90. BIN  packages/doc/sel_conflict.png
  91. BIN  packages/doc/update.png
  92. BIN  packages/doc/warning.png
  93. +2 −0  packages/include/.cvsignore
  94. +8 −0 packages/include/Makefile.am
  95. +181 −0 packages/include/installationCallback.ycp
  96. +1,093 −0 packages/include/packageHandle.ycp
  97. +393 −0 packages/include/selectionHandle.ycp
  98. +7 −0 packages/include/testsuite/.cvsignore
  99. +10 −0 packages/include/testsuite/Makefile.am
  100. +2 −0  packages/include/testsuite/config/default.exp
  101. +5 −0 packages/include/testsuite/config/unix.exp
  102. +2 −0  packages/include/testsuite/config/unknown.exp
  103. +1 −0  packages/include/testsuite/data/README
  104. +5 −0 packages/include/testsuite/data/cdrom.ycp
  105. +5 −0 packages/include/testsuite/data/cdsr0.ycp
  106. +5 −0 packages/include/testsuite/data/cdwrong.ycp
  107. +5 −0 packages/include/testsuite/data/dvd.ycp
  108. +6 −0 packages/include/testsuite/data/harddisk.ycp
  109. +7 −0 packages/include/testsuite/data/netone.ycp
  110. +8 −0 packages/include/testsuite/data/netsplit.ycp
  111. +3 −0  packages/include/testsuite/differr
  112. +3 −0  packages/include/testsuite/diffout
  113. +85 −0 packages/include/testsuite/lib/package_modules_init.exp
  114. +12 −0 packages/include/testsuite/package_modules.test/ycp.exp
  115. +19 −0 packages/include/testsuite/tests/InstMedia.cdrom.err
  116. +1 −0  packages/include/testsuite/tests/InstMedia.cdrom.out
  117. +19 −0 packages/include/testsuite/tests/InstMedia.cdsr0.err
  118. +1 −0  packages/include/testsuite/tests/InstMedia.cdsr0.out
  119. +19 −0 packages/include/testsuite/tests/InstMedia.cdwrong.err
  120. +1 −0  packages/include/testsuite/tests/InstMedia.cdwrong.out
  121. +19 −0 packages/include/testsuite/tests/InstMedia.dvd.err
  122. +1 −0  packages/include/testsuite/tests/InstMedia.dvd.out
  123. 0  packages/include/testsuite/tests/InstMedia.err
  124. +19 −0 packages/include/testsuite/tests/InstMedia.harddisk.err
  125. +1 −0  packages/include/testsuite/tests/InstMedia.harddisk.out
  126. +19 −0 packages/include/testsuite/tests/InstMedia.netone.err
  127. +1 −0  packages/include/testsuite/tests/InstMedia.netone.out
  128. +19 −0 packages/include/testsuite/tests/InstMedia.netsplit.err
  129. +1 −0  packages/include/testsuite/tests/InstMedia.netsplit.out
  130. 0  packages/include/testsuite/tests/InstMedia.out
  131. +32 −0 packages/include/testsuite/tests/InstMedia.ycp
  132. +6 −0 packages/include/testsuite/tests/runtest.sh
  133. +380 −0 packages/inst_rpmcopy.ycp
  134. +318 −0 packages/inst_smbsource.ycp
  135. +764 −0 packages/inst_source.ycp
  136. +360 −0 packages/inst_sw_details.ycp
  137. +356 −0 packages/inst_sw_select.ycp
  138. +1,690 −0 packages/inst_sw_single.ycp
  139. +2 −0  packages/modules/.cvsignore
  140. +876 −0 packages/modules/InstMedia.ycp
  141. +19 −0 packages/modules/Makefile.am
  142. +390 −0 packages/modules/MediaUI.ycp
  143. +271 −0 packages/modules/PackageInstallation.ycp
  144. +297 −0 packages/modules/PackageSelectionIO.ycp
  145. +729 −0 packages/modules/Packages.ycp
  146. +53 −0 packages/modules/PackagesUI.ycp
  147. +1,189 −0 packages/modules/SlideShow.ycp
  148. +431 −0 packages/modules/SpaceCalculation.ycp
  149. +11 −0 packages/testsuite/.cvsignore
  150. +16 −0 packages/testsuite/Makefile.am
  151. +2 −0  packages/testsuite/config/default.exp
  152. +104 −0 packages/testsuite/config/unix.exp
  153. +2 −0  packages/testsuite/config/unknown.exp
  154. +75 −0 packages/testsuite/install_inf.ycp
  155. +76 −0 packages/testsuite/lib/packages_init.exp
  156. +1 −0  packages/testsuite/lib/test.exp
  157. +68 −0 packages/testsuite/lib/test_init.exp
  158. +19 −0 packages/testsuite/old-tests/ChangeCD.err
  159. +52 −0 packages/testsuite/old-tests/ChangeCD.out
  160. +84 −0 packages/testsuite/old-tests/ChangeCD.ycp
  161. 0  packages/testsuite/old-tests/EvaluateFreeSpace.err
  162. +4 −0 packages/testsuite/old-tests/EvaluateFreeSpace.out
  163. +91 −0 packages/testsuite/old-tests/EvaluateFreeSpace.ycp
  164. 0  packages/testsuite/old-tests/GetBootDevice.err
  165. +6 −0 packages/testsuite/old-tests/GetBootDevice.out
  166. +30 −0 packages/testsuite/old-tests/GetBootDevice.ycp
  167. 0  packages/testsuite/old-tests/evaluateFreeSpace.err
  168. +4 −0 packages/testsuite/old-tests/evaluateFreeSpace.out
  169. +152 −0 packages/testsuite/old-tests/evaluateFreeSpace.ycp
  170. +2 −0  packages/testsuite/old-tests/runtest.sh
  171. +612 −0 packages/testsuite/package_tests.ycp
  172. +12 −0 packages/testsuite/packages.test/ycp.exp
  173. +30 −0 packages/testsuite/packages_inf.ycp
  174. +45 −0 packages/testsuite/run/runtest.sh
  175. +91 −0 packages/testsuite/suse/setup/descr/Advanced-Devel.sel
  176. +73 −0 packages/testsuite/suse/setup/descr/Games.sel
  177. +127 −0 packages/testsuite/suse/setup/descr/Gnome.sel
  178. +144 −0 packages/testsuite/suse/setup/descr/Kde-Desktop.sel
  179. +87 −0 packages/testsuite/suse/setup/descr/Kde.sel
  180. +63 −0 packages/testsuite/suse/setup/descr/LAMP.sel
  181. +55 −0 packages/testsuite/suse/setup/descr/Linux-Devel.sel
  182. +22 −0 packages/testsuite/suse/setup/descr/MD5SUMS
  183. +360 −0 packages/testsuite/suse/setup/descr/Minimal+X11.sel
  184. +246 −0 packages/testsuite/suse/setup/descr/Minimal.sel
  185. +132 −0 packages/testsuite/suse/setup/descr/Multimedia.sel
  186. +110 −0 packages/testsuite/suse/setup/descr/Network.sel
  187. +520 −0 packages/testsuite/suse/setup/descr/Standard.sel
  188. +186 −0 packages/testsuite/suse/setup/descr/SuSE-Documentation.sel
  189. +62,401 −0 packages/testsuite/suse/setup/descr/common.pkd
  190. +30,651 −0 packages/testsuite/suse/setup/descr/cs.pkd
  191. +32,758 −0 packages/testsuite/suse/setup/descr/de.pkd
  192. +547 −0 packages/testsuite/suse/setup/descr/default.sel
  193. +32,143 −0 packages/testsuite/suse/setup/descr/en.pkd
  194. +31,620 −0 packages/testsuite/suse/setup/descr/es.pkd
  195. +30,769 −0 packages/testsuite/suse/setup/descr/fr.pkd
  196. +32,758 −0 packages/testsuite/suse/setup/descr/german.pkd
  197. +18 −0 packages/testsuite/suse/setup/descr/info
  198. +1 −0  packages/testsuite/suse/setup/descr/pacsel/OBSOLETE
  199. +100 −0 packages/testsuite/suse/setup/descr/update.in_
  200. +1 −0  packages/testsuite/suse/setup/du/MD5SUMS
  201. +81,715 −0 packages/testsuite/suse/setup/du/du.dir
  202. +128 −0 packages/testsuite/test_instruction.txt
  203. +1 −0  packages/testsuite/test_package
  204. 0  packages/testsuite/tests/empty.err
  205. 0  packages/testsuite/tests/empty.out
  206. +1 −0  packages/testsuite/tests/empty.ycp
  207. +44 −0 yast2-packager.spec.in
View
21 .cvsignore
@@ -0,0 +1,21 @@
+Makefile
+Makefile.in
+Makefile.am
+configure
+config.h
+config.h.in
+config.cache
+config.status
+config.sub
+config.guess
+stamp-h*
+libtool
+config.log
+aclocal.m4
+depcomp
+install-sh
+ltmain.sh
+missing
+mkinstalldirs
+autom4te.cache
+configure.in
View
1  MAINTAINER
@@ -0,0 +1 @@
+Arvin Schnell <arvin@suse.de>
View
16 Makefile.cvs
@@ -0,0 +1,16 @@
+
+configure: all
+ ./configure
+
+all:
+ y2tool y2autoconf
+ y2tool y2automake
+ autoreconf --force --install
+
+install: configure
+ make
+ make install
+
+reconf: all
+ ./config.status --recheck
+ ./config.status
View
1  RPMNAME
@@ -0,0 +1 @@
+yast2-packager
View
1  VERSION
@@ -0,0 +1 @@
+2.6.0
View
8 client-packager/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+*.lo
+.deps
+.libs
+y2qt
+*.la
+packager
View
5 client-packager/Makefile.am
@@ -0,0 +1,5 @@
+#
+# Makefile.am for packager/client-packager
+#
+
+SUBDIRS = src testsuite doc
View
3  client-packager/doc/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+PKGINFO.html
View
5 client-packager/doc/Makefile.am
@@ -0,0 +1,5 @@
+#
+# Makefile.am for packager/doc
+#
+
+SUBDIRS = autodocs
View
3  client-packager/doc/autodocs/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+*.html
View
19 client-packager/doc/autodocs/Makefile.am
@@ -0,0 +1,19 @@
+#
+# Makefile.am for packager/doc/autodocs
+#
+htmldir = $(docdir)/packager/autodocs
+html_DATA = \
+ Rpm_Installer.html \
+ Y2CCPackager.html \
+ Y2PackagerComponent.html \
+ heir.html index.html
+
+EXTRA_DIST = $(html_DATA)
+
+CLEANFILES = $(html_DATA)
+
+$(filter-out index.html, $(html_DATA)): index.html
+index.html: $(srcdir)/../../src/*.h
+ cd $(srcdir)/../../src; @ybindir@/ydoc -p @RPMNAME@ *.h
+ mv -f $(srcdir)/../../src/*.html .
+
View
9 client-packager/src/.cvsignore
@@ -0,0 +1,9 @@
+Makefile.in
+Makefile
+*.o
+*.lo
+*.la
+.deps
+.libs
+packager
+*.kdoc
View
12 client-packager/src/Makefile.am
@@ -0,0 +1,12 @@
+#
+# Makefile.am for packager/src
+#
+
+plugin_LTLIBRARIES = libpy2packager.la
+libpy2packager_la_SOURCES = \
+ Y2CCPackager.cc Y2CCPackager.h \
+ Y2PackagerComponent.cc Y2PackagerComponent.h \
+ Rpm_Installer.cc Rpm_Installer.h
+libpy2packager_la_LDFLAGS = -version-info 2:0
+
+INCLUDES = -I$(includedir)
View
547 client-packager/src/Rpm_Installer.cc
@@ -0,0 +1,547 @@
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+
+using std::ofstream;
+using std::ios;
+using std::endl;
+
+#include "Rpm_Installer.h"
+#include <y2/ExternalDataSource.h>
+#include <ycp/y2log.h>
+
+
+Rpm_Installer::Rpm_Installer(string name_of_root,
+ string name_of_dbpath,
+ string package_name)
+ : rootfs(name_of_root),
+ rpmDBPath(name_of_dbpath),
+ package(package_name),
+ globaLogShortRPM ( false ),
+ process(0),
+ exit_code(-1)
+{
+}
+
+
+Rpm_Installer::~Rpm_Installer()
+{
+ delete process;
+}
+
+
+// Create all parent directories of @param name, as necessary
+
+static void
+create_directories(string name)
+{
+ size_t pos = 0;
+
+ while (pos = name.find('/', pos + 1), pos != string::npos)
+ mkdir (name.substr(0, pos).c_str(), 0777);
+}
+
+
+// prepend rootfs if needed
+// check if rootfs ends in "/" and if path begins with "/" (rooted_path)
+//
+
+static const string prepend_rootfs (const string& rootfs, const string& path)
+{
+ bool rooted_path = (path[0] == '/');
+
+ // remove trailing '/'
+
+ if (rootfs == "/")
+ return (rooted_path ? path : (string ("/")+path));
+
+ if (rootfs[rootfs.size()-1] == '/') {
+ if (!rooted_path) {
+ string norootpath (path, 1);
+ return rootfs + norootpath;
+ }
+ return rootfs + path;
+ }
+ return (rooted_path ? (rootfs + path) : (rootfs + "/" + path));
+}
+
+
+// Splitting a string into columns
+
+void Rpm_Installer::splitt( string source, string *column, int max_column,
+ string seperator )
+{
+ string::size_type begin, end;
+ int counter;
+
+ for ( counter = 0; counter<max_column ; counter++ )
+ {
+ column[counter] = "";
+ }
+
+ // evaluate all columns
+ begin = source.find_first_not_of ( seperator );
+ counter = 0;
+ while ( begin != string::npos && counter < max_column )
+ {
+ end = source.find_first_of ( seperator, begin );
+
+ // line-end ?
+ if ( end == string::npos )
+ {
+ end= source.length();
+ }
+ if ( counter < max_column-1 )
+ {
+ column[counter].assign ( source, begin, end-begin );
+ }
+ else
+ {
+ // Rest of string into the last value
+ column[counter].assign (source, begin, string::npos);
+ }
+
+ begin = source.find_first_not_of ( seperator, end );
+ counter++;
+ }
+
+ for ( counter = 0; counter<max_column ; counter++ )
+ {
+ // extract \n
+ if (column[counter][column[counter].length()-1] == '\n' )
+ {
+ column[counter].assign ( column[counter],
+ 0,
+ column[counter].length()-1 );
+ }
+ }
+}
+
+
+// Logging rpm-command
+
+void Rpm_Installer::logRPM ( string line, bool onlyLongFormat,
+ bool withoutCR )
+{
+ if ( line[0] != '%' && line[1] != '%')
+ {
+ // logging no percent display
+ string filename = prepend_rootfs (rootfs, "/var/log/y2logRPM");
+ ofstream fpRpmLog ( filename.c_str(), ios::app | ios::ate );
+ if ( fpRpmLog )
+ {
+ fpRpmLog << line << endl;
+ }
+
+ if ( !onlyLongFormat )
+ {
+ // short form of logging
+ filename = prepend_rootfs (rootfs, "/var/log/y2logRPMShort");
+ ofstream fpRpmLogShort ( filename.c_str() , ios::app | ios::ate );
+ if ( fpRpmLogShort )
+ {
+
+ //
+ // filter out message if backup does not differ from config file
+ //
+ // /etc/crontab created as /etc/crontab.rpmnew
+ if ( line.find( "saved as" ) != string::npos ||
+ line.find( "created as" ) != string::npos )
+ {
+ string column[5];
+ string command;
+
+ fpRpmLogShort << line << endl;
+
+ splitt( line, column, 5, " " );
+ command = "diff -q ";
+ command += column[1] + " ";
+ command += column[4];
+ if ( fpRpmLog )
+ {
+ fpRpmLog << command << endl;
+ }
+
+ command += " >/dev/null 2>&1";
+
+ if ( system ( command.c_str() ) == 0 )
+ {
+ unlink( column[4].c_str() );
+ if ( fpRpmLog )
+ {
+ fpRpmLog << "removing: " << column[4] << endl ;
+ }
+ }
+ else
+ {
+ if ( fpRpmLog )
+ {
+ fpRpmLog << "Files " << column[1] << " and "
+ << column[4] << " differ" << endl;
+ }
+ string::size_type pos = column[1].find_last_of ( "^*/" );
+ string logfile;
+
+ if ( pos != string::npos )
+ {
+ string file;
+ file.assign (column[1], pos + 1, string::npos);
+ logfile = prepend_rootfs (rootfs,
+ "/var/adm/notify/warnings/Configfile_"
+ + file) ;
+ }
+ else
+ {
+ logfile = prepend_rootfs (rootfs,
+ "/var/adm/notify/warnings/Configfile_"
+ + column[1]) ;
+ }
+ ofstream log( logfile.c_str(), ios::out | ios::app );
+ log << line << endl;
+ log.close();
+ }
+ }
+
+ //
+ // filter out errors for nonempty and missing dirs upon delete
+ //
+ else if ( line.find ( "package " ) != string::npos &&
+ line.find ( " not " ) != string::npos &&
+ ( line.find ( "listed" ) != string::npos ||
+ line.find ( "found" ) != string::npos ) &&
+ line.find ( "in " ) != string::npos &&
+ line.find ( " index" ) )
+ {
+ // nothing !!!
+ }
+ else if ( line.find( "removal of" ) != string::npos ||
+ line.find( "rmdir of" ) != string::npos ||
+ line.find( "cannot remove" ) != string::npos )
+ {
+
+ if ( line.find( "directory not empty" ) != string::npos ||
+ line.find( "operation not permitted" ) != string::npos ||
+ line.find( "no such file or directory" ) != string::npos )
+ {
+ // nothing !!!
+ }
+ }
+ else
+ {
+ // logging anyway
+ if ( !withoutCR )
+ {
+ fpRpmLogShort << line << endl;
+ }
+ else
+ {
+ fpRpmLogShort << line << " ";
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// Initialize the rpm database
+
+void
+Rpm_Installer::init_database()
+{
+ y2debug ("init_database");
+ create_directories (prepend_rootfs (rootfs, rpmDBPath));
+ const char *const opts[] = { "--initdb" };
+ globaLogShortRPM = false;
+ run_rpm(sizeof(opts) / sizeof(*opts), opts);
+}
+
+
+// Query the name of the current package
+
+string
+Rpm_Installer::query_package_name()
+{
+ return query_package("%{NAME}");
+}
+
+
+// Return the contents of the preinstall script for the current package
+
+string
+Rpm_Installer::query_preinstall_script()
+{
+ string script = query_package("%{PREIN}");
+ if (script == "(none)")
+ script = "";
+ return script;
+}
+
+
+// Return the contents of the postinstall script for the current package
+
+string
+Rpm_Installer::query_postinstall_script()
+{
+ string script = query_package("%{POSTIN}");
+ if (script == "(none)")
+ script = "";
+ return script;
+}
+
+
+bool
+Rpm_Installer::is_installed()
+{
+ string packageName = query_package_name();
+ const char *const opts[] = {
+ "-q", "--qf", "%{NAME}", packageName.c_str()
+ };
+ globaLogShortRPM = false;
+ run_rpm(sizeof(opts) / sizeof(*opts), opts, ExternalProgram::Discard_Stderr);
+ string value ="";
+ string output = process->receiveLine();
+
+ while ( output.length() > 0 )
+ {
+ value += output;
+ output = process->receiveLine();
+ }
+
+ logRPM ( value, true );
+
+ status();
+ if ( value.length() > 0 )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+// Query the current package using the specified query format
+
+string
+Rpm_Installer::query_package(const char *format)
+{
+// y2debug ("query_package %s", format);
+ const char *const opts[] = {
+ "-q", "-p", "--qf", format, package.c_str()
+ };
+ globaLogShortRPM = false;
+ run_rpm(sizeof(opts) / sizeof(*opts), opts, ExternalProgram::Discard_Stderr);
+ string value ="";
+ string output = process->receiveLine();
+
+ while ( output.length() > 0 )
+ {
+ value += output;
+ output = process->receiveLine();
+ }
+
+ logRPM ( value, true );
+
+ status();
+ return value;
+}
+
+
+// Install the current package
+
+void
+Rpm_Installer::install_package(bool noscripts)
+{
+ const char *opts[] = {
+ "-U", "--replacepkgs", "--oldpackage", "--replacefiles",
+ "--nodeps", "--ignoresize", "--percent",
+ 0, 0
+ };
+ int n_opts = sizeof(opts) / sizeof(*opts) - 2;
+ struct stat dummyStat;
+
+ if (noscripts)
+ opts[n_opts++] = "--noscripts";
+ opts[n_opts++] = package.c_str();
+
+ globaLogShortRPM = true;
+
+ run_rpm(n_opts, opts,
+ noscripts ? ExternalProgram::Discard_Stderr
+ : ExternalProgram::Stderr_To_Stdout);
+
+ string::size_type pos = package.find_last_of ( "/" );
+ string packageName;
+
+ if ( pos != string::npos )
+ {
+ packageName.assign (package, pos + 1, string::npos);
+ }
+ else
+ {
+ packageName = package;
+ }
+
+ pos = packageName.find ( ".rpm" );
+ if ( pos != string::npos )
+ {
+ packageName.assign ( packageName, 0, pos );
+ }
+
+ string output = "Installing ";
+ output += packageName.c_str();
+ logRPM ( output,false, true );
+
+ // Checking, if rpm-file exists.
+ if ( stat( package.c_str(), &dummyStat ) == -1 )
+ {
+ output = "ERRROR: file ";
+ output += package + " does not exists.";
+ logRPM ( output,false );
+ }
+}
+
+
+// Uninstall the current package
+
+void
+Rpm_Installer::remove_package()
+{
+ const char *const opts[] = {
+ "-e", "--nodeps", package.c_str()
+ };
+
+ globaLogShortRPM = true;
+
+ run_rpm(sizeof(opts) / sizeof(*opts), opts);
+
+ string::size_type pos = package.find_last_of ( "/" );
+ string packageName;
+
+ if ( pos != string::npos )
+ {
+ packageName.assign (package, pos + 1, string::npos);
+ }
+ else
+ {
+ packageName = package;
+ }
+
+ pos = packageName.find ( ".rpm" );
+ if ( pos != string::npos )
+ {
+ packageName.assign ( packageName, 0, pos );
+ }
+
+ string output = "Removing ";
+ output += packageName.c_str();
+ logRPM ( output,false, true );
+}
+
+
+// Run rpm with the specified arguments, handling stderr as specified
+// by disp
+
+void
+Rpm_Installer::run_rpm(int n_opts, const char *const *options,
+ ExternalProgram::Stderr_Disposition disp)
+{
+ exit_code = -1;
+ int argc = n_opts + 1 + 5 /* rpm --root <root> --dbpath <dbpath>*/
+ + 1 /* NULL */;
+
+ // Create the argument array
+ const char *argv[argc];
+ int i = 0;
+ argv[i++] = "rpm";
+ argv[i++] = "--root";
+ argv[i++] = rootfs.c_str();
+ argv[i++] = "--dbpath";
+ argv[i++] = rpmDBPath.c_str();
+ for (int j = 0; j < n_opts; j++)
+ argv[i++] = options[j];
+ argv[i] = 0;
+
+
+ string output = "";
+ int k;
+
+ for ( k = 0; k < argc-2; k++ )
+ {
+ output = output + " " + argv[k];
+ }
+
+ y2debug ("rpm command: %s", output.c_str() );
+ logRPM ( output, true );
+
+ // Launch the program
+ process = new ExternalProgram(argv, disp);
+}
+
+
+// Read a line from the rpm process
+
+bool
+Rpm_Installer::read_line(string &line)
+{
+ line = process->receiveLine();
+ if (line.length() == 0)
+ return false;
+ if (line[line.length() - 1] == '\n')
+ line.erase(line.length() - 1);
+
+ if ( globaLogShortRPM )
+ {
+ logRPM ( line, false );
+ }
+ else
+ {
+ logRPM ( line, true ); // only long-form of logging
+ }
+
+ return true;
+}
+
+
+// Return the exit status of the rpm process, closing the connection if
+// not already done
+
+int
+Rpm_Installer::status()
+{
+ if (exit_code == -1)
+ exit_code = process->close();
+
+ char number[20];
+ sprintf ( number ,"%d", exit_code );
+ string output = "Return :";
+ output += number;
+ logRPM ( output,true );
+
+ if ( globaLogShortRPM )
+ {
+ if ( exit_code == 0 )
+ {
+ logRPM ( "... OK",false );
+ }
+ else
+ {
+ logRPM ( "... ERROR",false );
+ }
+ }
+ return exit_code;
+}
+
+
+// Forcably kill the rpm process
+
+void
+Rpm_Installer::kill()
+{
+ if (process) process->kill();
+}
View
149 client-packager/src/Rpm_Installer.h
@@ -0,0 +1,149 @@
+// -*- C++ -*-
+
+#ifndef Rpm_Installer_h
+#define Rpm_Installer_h
+
+#include <YCP.h>
+#include <y2/ExternalProgram.h>
+#include <fstream>
+#include <iostream>
+
+
+/**
+ * @short Interface to the rpm program
+ */
+
+class Rpm_Installer
+{
+public:
+ /**
+ * Create an new instance.
+ * @param name_of_root The name of the install root
+ * @param name_of_dbpath The path of the rpm-db
+ * @param package_name The full name of the package file if any
+ */
+ Rpm_Installer(string name_of_root,
+ string name_of_dbpath,
+ string package_name = "");
+
+ /**
+ * Clean up.
+ */
+ ~Rpm_Installer();
+
+ /**
+ * Initialize the rpm database
+ */
+ void init_database();
+
+ /**
+ * Install the current package.
+ * @param noscript If true don't execute install scripts
+ */
+ void install_package(bool noscripts = false);
+
+ /**
+ * Uninstall the current package.
+ */
+ void remove_package();
+
+ /**
+ * Query the name of the current package.
+ */
+ string query_package_name();
+
+ /**
+ * Return the contents of the preinstall script for the current package.
+ */
+ string query_preinstall_script();
+
+ /**
+ * Return the contents of the postinstall script for the current package.
+ */
+ string query_postinstall_script();
+
+ /**
+ * Query the current package.
+ * @param format The query format to use.
+ */
+ string query_package( const char *format );
+
+ /**
+ * Check, if the package is installed
+ */
+ bool is_installed();
+
+ /**
+ * Read a line from the rpm process.
+ */
+ bool read_line(string &line);
+
+ /**
+ * Return the exit status of the rpm process, closing the connection if
+ * not already done.
+ */
+ int status();
+
+ /**
+ * Forcably kill the rpm process
+ */
+ void kill();
+
+ /**
+ * Logging rpm-command and results /var/log/y2logRPM and
+ * /var/log/y2logRPMShort
+ */
+ void logRPM ( string line, bool onlyLongFormat, bool withoutCR = false );
+
+private:
+
+ /**
+ * The name of the install root.
+ */
+ string rootfs;
+
+ /**
+ * Path of the rpm-db
+ */
+ string rpmDBPath;
+
+ /**
+ * The name of the current package.
+ */
+ string package;
+
+
+ /**
+ * Flag, if the output and the return-value
+ * have to be logged in the short form
+ **/
+ bool globaLogShortRPM;
+
+ /**
+ * The connection to the rpm process.
+ */
+ ExternalProgram *process;
+
+ /**
+ * Splitting strings
+ **/
+ void splitt( string source, string *column, int max_column,
+ string seperator );
+
+ /**
+ * Run rpm with the specified arguments and handle stderr.
+ * @param n_opts The number of arguments
+ * @param options Array of the arguments, @ref n_opts elements
+ * @param stderr_disp How to handle stderr, merged with stdout by default
+ */
+ void run_rpm(int n_opts, const char *const *options,
+ ExternalProgram::Stderr_Disposition stderr_disp =
+ ExternalProgram::Stderr_To_Stdout);
+
+ /**
+ * The exit code of the rpm process, or -1 if not yet known.
+ */
+ int exit_code;
+};
+
+#endif
View
5 client-packager/src/Y2CCPackager.cc
@@ -0,0 +1,5 @@
+#include "Y2CCPackager.h"
+
+// The global variabe to register Y2CCPackager to the Y2ComponentBroker
+
+Y2CCPackager g_y2ccpackager;
View
27 client-packager/src/Y2CCPackager.h
@@ -0,0 +1,27 @@
+#ifndef Y2CCPackager_h
+#define Y2CCPackager_h
+
+#include <Y2.h>
+#include "Y2PackagerComponent.h"
+
+class Y2CCPackager : public Y2ComponentCreator
+{
+public:
+ // Create a packager component creator and register it
+ Y2CCPackager() : Y2ComponentCreator(Y2ComponentBroker::BUILTIN)
+ {}
+
+ // The packager component is a client
+ bool isServerCreator() const { return false; }
+
+ // Create a new packager component if name is our name
+ Y2Component *create(const char *name) const
+ {
+ if (strcmp(name, Y2PackagerComponent::component_name().c_str()) == 0)
+ return new Y2PackagerComponent();
+ else
+ return 0;
+ }
+};
+
+#endif // Y2CCPackager_h
View
381 client-packager/src/Y2PackagerComponent.cc
@@ -0,0 +1,381 @@
+/*
+ * Y2PackagerComponent.cc
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/statvfs.h>
+
+#include "Y2PackagerComponent.h"
+#include "Rpm_Installer.h"
+#include <ycp/y2log.h>
+
+#define RETURN_OK YCPSymbol("ok", true) // `ok
+#define RETURN_ERROR YCPSymbol("error", true) // `error
+#define RETURN_CANCEL YCPSymbol("cancel", true) // `cancel
+
+
+static void
+get_disk_stats(const char *fs, long long *used, long long *size)
+{
+ struct statvfs sb;
+ if (statvfs(fs, &sb) < 0)
+ {
+ *used = *size = -1;
+ return;
+ }
+ long long blocksize = sb.f_frsize ? : sb.f_bsize;
+ *size = sb.f_blocks * blocksize;
+ *used = (sb.f_blocks - sb.f_bfree) * blocksize;
+}
+
+// PackagerComponent
+
+YCPValue
+Y2PackagerComponent::doActualWork(const YCPList& options, Y2Component *displayserver)
+{
+ report_macro = (options->value(0)->isVoid() ? ""
+ : options->value(0)->asString()->value());
+
+ YCPValue op = options->value(1);
+ string op_name =
+ (op->isTerm() ? op->asTerm()->symbol() : op->asSymbol())->symbol();
+ if (op_name == "init")
+ operation = Init;
+ else if (op_name == "add" || op_name == "remove")
+ {
+ operation = op_name == "add" ? Add : Remove;
+ package_prefix = op->asTerm()->value(0)->asString()->value();
+ if (package_prefix[package_prefix.size()-1] != '/')
+ package_prefix = package_prefix + "/";
+ packages = op->asTerm()->value(1)->asList();
+ }
+ else
+ y2error ("Invalid operation: %s", op_name.c_str());
+
+ // Parse options
+ int argc = options->size();
+ for (int i = 2; i < argc; i++)
+ {
+ YCPValue v = options->value(i);
+ YCPTerm t = v->isTerm() ? v->asTerm() : YCPNull();
+ string option = v->isTerm() ? t->symbol()->symbol()
+ : v->asSymbol()->symbol();
+ if (option == "root")
+ // Name of root filesystem
+ rootfs = t->value(0)->asString()->value();
+ else if (option == "number")
+ start_number = t->value(0)->asInteger()->value();
+ else if (option == "rpmpath")
+ rpmDBPath = t->value(0)->asString()->value();
+ else if (option == "manual_scripts")
+ manual_scripts = true;
+ }
+
+ y2debug ("rootfs = %s", rootfs.c_str());
+ y2debug ("rpmDBPath = %s", rpmDBPath.c_str());
+ y2debug ("operation = %s", operation == Init ? "init" : operation == Add ? "add" : "remove");
+ if (package_prefix[0])
+ y2debug ("Package prefix = %s", package_prefix.c_str());
+ if (manual_scripts)
+ y2debug ("manual_scripts");
+
+ switch (operation)
+ {
+ case Init:
+ {
+ Rpm_Installer rpm(rootfs, rpmDBPath);
+ rpm.init_database();
+ if (rpm.status() == 0) return RETURN_OK;
+ else return RETURN_ERROR;
+ }
+
+ case Add:
+ {
+ int n_files = packages->size();
+
+ y2debug ("Installing: root = %s%s", rootfs.c_str(), manual_scripts ? ", manual_scripts" : "");
+
+ YCPSymbol returncode = RETURN_OK;
+ for (int current_number = 0; current_number < n_files;
+ current_number++)
+ {
+ YCPValue package =
+ packages->value(current_number)->asList()->value(0);
+ string fullname = package_prefix + package->asString()->value();
+ Rpm_Installer rpm(rootfs, rpmDBPath, fullname);
+
+ // Figure out the package name
+ string current_package = rpm.query_package_name();
+
+ if (current_package == "")
+ {
+ // Skip missing packages
+ y2warning ("Package %s not found", fullname.c_str());
+
+ rpm.logRPM ( "Package " + fullname + " not found", false );
+ // set RETURN_ERROR and report_progress with error=true
+ returncode = RETURN_ERROR;
+ report_progress(displayserver,
+ fullname, current_number, 0, true);
+ continue;
+ }
+
+ y2milestone ("Installing %s", current_package.c_str());
+
+ YCPValue val =
+ report_progress(displayserver,
+ current_package, current_number, 0, false);
+ if (!val->isVoid())
+ {
+ rpm.kill();
+ return val;
+ }
+
+ bool is_installed = rpm.is_installed();
+
+ if (manual_scripts)
+ // Execute preinstall script
+ execute_script(rpm.query_preinstall_script(),
+ is_installed);
+
+ // Start installation
+ rpm.install_package(manual_scripts);
+
+ string line;
+ double old_percent = 0.0;
+ while (rpm.read_line(line))
+ {
+ if (line[0] == '%' && line[1] == '%')
+ {
+ double percent;
+ sscanf (line.c_str () + 2, "%lg", &percent);
+ if (percent >= old_percent + 5.0)
+ {
+ old_percent = int (percent / 5) * 5;
+ YCPValue val =
+ report_progress (displayserver, current_package,
+ current_number, percent, false);
+ if (!val->isVoid())
+ {
+ rpm.kill();
+ return val;
+ }
+ }
+ }
+ else
+ y2warning ("rpm: %s", line.c_str());
+ }
+ int rpm_status = rpm.status();
+
+ if (rpm_status != 0)
+ {
+ y2error ("rpm returned %d", rpm_status);
+ returncode = RETURN_ERROR;
+ report_progress (displayserver, current_package,
+ current_number, 100, true);
+ }
+
+ if (manual_scripts)
+ // Execute postinstall script
+ execute_script(rpm.query_postinstall_script(),
+ is_installed);
+ }
+
+ y2debug("RETURN from packager: %s", returncode->toString().c_str());
+
+ return returncode;
+ break;
+ }
+
+ case Remove:
+ {
+ int n_files = packages->size();
+
+ y2debug ("Removing: root = %s%s", rootfs.c_str(), manual_scripts ? ", manual_scripts" : "");
+
+ YCPSymbol returncode = RETURN_OK;
+ for (int current_number = 0; current_number < n_files;
+ current_number++)
+ {
+ YCPValue package =
+ packages->value(current_number)->asList()->value(0);
+ string package_name = package->asString()->value();
+
+ Rpm_Installer rpm(rootfs, rpmDBPath, package_name);
+
+ // Figure out the package name
+ package =
+ packages->value(current_number)->asList()->value(1);
+ string current_package = package->asString()->value();
+
+ y2milestone ("Deleting %s", current_package.c_str());
+
+ YCPValue val =
+ report_progress(displayserver,
+ package_name, current_number, 0, false);
+ if (!val->isVoid())
+ {
+ rpm.kill();
+ return val;
+ }
+
+ // Start remove
+ rpm.remove_package();
+
+ string line;
+ double old_percent = 0.0;
+ while (rpm.read_line(line))
+ {
+ if (line[0] == '%' && line[1] == '%')
+ {
+ double percent;
+ sscanf (line.c_str () + 2, "%lg", &percent);
+ if (percent >= old_percent + 5.0)
+ {
+ old_percent = int (percent / 5) * 5;
+ YCPValue val =
+ report_progress (displayserver, package_name,
+ current_number, percent, false);
+ if (!val->isVoid())
+ {
+ rpm.kill();
+ return val;
+ }
+ }
+ }
+ else
+ y2warning ("rpm: %s", line.c_str());
+ }
+ int rpm_status = rpm.status();
+ if (rpm_status != 0)
+ {
+ y2warning ("rpm returned %d", rpm_status);
+ returncode = RETURN_ERROR;
+ report_progress (displayserver, package_name,
+ current_number, 100, true);
+ }
+ }
+ return returncode;
+ break;
+ }
+ default:
+ return YCPVoid();
+ }
+}
+
+
+/*
+ report progress to UI
+
+ send <report_macro> ( <name>, <label>, <percent>, <number>, <disk_used>, <disk_size>)
+
+ to UI
+
+ Unchanged values (i.e. <name> and <label> are nil (YCPVoid())
+
+*/
+
+
+static string last_name; // leave here due to compiler bug
+
+YCPValue
+Y2PackagerComponent::report_progress(Y2Component *displayserver,
+ string name, int number, double percent,
+ bool error)
+{
+ if (report_macro == "")
+ return YCPVoid();
+
+ YCPTerm t(report_macro, false);
+ if (name != last_name ||
+ error )
+ {
+ t->add(YCPString(name));
+ YCPValue this_package = packages->value(number);
+ t->add(this_package->asList()->value(1));
+ last_name = name;
+ }
+ else {
+ t->add(YCPVoid());
+ t->add(YCPVoid());
+ }
+
+ t->add(YCPInteger((long long)percent));
+ t->add(YCPInteger(number + start_number));
+
+ long long disk_used, disk_size;
+
+ get_disk_stats(rootfs.c_str(), &disk_used, &disk_size);
+
+ t->add(YCPInteger(disk_used));
+ t->add(YCPInteger(disk_size));
+ t->add(YCPBoolean(error));
+
+ YCPValue val = displayserver->evaluate(t);
+ if (!val->isVoid())
+ {
+ if (val->isSymbol() && val->asSymbol()->symbol() == "cancel") return val;
+ else
+ {
+ y2error ("displayserver returned %s", val->toString().c_str());
+ return RETURN_ERROR;
+ }
+ }
+ return val;
+}
+
+void
+Y2PackagerComponent::execute_script(string script, bool is_installed )
+{
+ if (script == "")
+ return;
+
+ string script_option = "1"; //new install
+ if ( is_installed )
+ {
+ script_option = "2"; // update
+ }
+
+ string full_script =
+ string("cd ") + rootfs + " || exit 1; " + script;
+
+ FILE* file = fopen( "/tmp/execute_script", "w" );
+
+ if ( ! file )
+ {
+ y2error("Can't open /tmp/execute_script for writing");
+ return;
+ }
+
+ fprintf( file,
+ "%s",
+ full_script.c_str() );
+
+ if ( file ) fclose( file );
+
+ const char *argv[] = {
+ "/bin/sh",
+ "/tmp/execute_script",
+ script_option.c_str(),
+ (char *) 0
+ };
+
+ ExternalProgram shell(argv, ExternalProgram::Stderr_To_Stdout);
+
+ string line;
+ while (1)
+ {
+ line = shell.receiveLine();
+ if (line.length() == 0)
+ break;
+ if (line[line.length() - 1] == '\n')
+ line.erase(line.length() - 1);
+ y2warning ("%s", line.c_str());
+ }
+ int status = shell.close();
+ if (status != 0)
+ y2warning ("shell returned %d", status);
+
+ remove ( "/tmp/execute_script" );
+}
View
92 client-packager/src/Y2PackagerComponent.h
@@ -0,0 +1,92 @@
+// -*- c++ -*-
+
+#ifndef Y2PackagerComponent_h
+#define Y2PackagerComponent_h
+
+#include <Y2.h>
+
+/**
+ * @short Install and uninstall packages
+ */
+class Y2PackagerComponent : public Y2Component
+{
+private:
+ // Name of macro to call for progress bars, or "" if quiet
+ string report_macro;
+
+ // What to do
+ enum { Init, Add, Remove } operation;
+
+ // List of package names
+ YCPList packages;
+
+ // Prefix for package names
+ string package_prefix;
+
+ // Name of the root filesystem, defaults to "/"
+ string rootfs;
+
+ // path of the rpm-DB
+ string rpmDBPath;
+
+ // Ordinal number of the first package
+ int start_number;
+
+ // Whether to execute install scripts manually
+ bool manual_scripts;
+
+public:
+ /**
+ * Create a new packager component
+ */
+ Y2PackagerComponent::Y2PackagerComponent()
+ : report_macro(""), packages(YCPNull()),
+ rootfs("/"), rpmDBPath( "/var/lib/rpm/" ), manual_scripts(false)
+ {}
+
+ /**
+ * What I'm called: "packager"
+ */
+ static string component_name() { return "packager"; }
+ string name() const { return component_name(); }
+
+ /**
+ * Do the actual work of installing and uninstalling
+ */
+ YCPValue doActualWork(const YCPList& options, Y2Component *displayserver);
+
+ /**
+ * Set the client arguments:
+ *
+ * packager(macro, operation, options...)
+ *
+ * macro is either nil or a symbol that is called during installation as
+ * macro(packname, packdescr, percent, number, disk_used, disk_size)
+ * packname name of current package
+ * packdesc package summary line
+ * percent how much of the current package is installed
+ * number the ordinal number of the current package
+ * beginning with start (default 1)
+ * disk_used used bytes on filesystem that contains the root
+ * disk_size total space in bytes on that filesystem
+ *
+ * Possible operations are:
+ * add(prefix, [package...]) install the packages
+ * remove(prefix, [package...]) uninstall the packages
+ * each package is a list [name, summary_line].
+ * init set up the root filesystem
+ *
+ * Possible options are:
+ * root(name) the root filesystem to use (defaut "/")
+ * number(start) number of the first package to install
+ * manual_scripts run install scripts manually
+ */
+private:
+ YCPValue report_progress(Y2Component *displayserver,
+ string name, int number, double percent,
+ bool error );
+
+ void execute_script(string script, bool is_installed );
+};
+
+#endif // Y2PackagerComponent_h
View
8 client-packager/testsuite/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+*.log
+*.sum
+site.exp
+.libs
+.deps
+y2packager
View
21 client-packager/testsuite/Makefile.am
@@ -0,0 +1,21 @@
+#
+# Makefile.am for packager/testsuite
+#
+
+AUTOMAKE_OPTIONS = dejagnu
+
+INCLUDES = -I$(includedir)
+
+noinst_PROGRAMS = y2packager
+y2packager_SOURCES = y2packager.cc
+
+y2packager_LDADD = -ly2 -lycp
+y2packager_LDFLAGS = -L$(libdir) \
+ -Xlinker --whole-archive \
+ $(plugindir)/libpy2stdio.la \
+ $(plugindir)/libpy2script.la \
+ ../src/libpy2packager.la \
+ -Xlinker --no-whole-archive
+
+clean-local:
+ rm -f tmp.err.* tmp.out.* *.log *.sum site.exp
View
0  client-packager/testsuite/y2packager.cc
No changes.
View
15 configure.in.in
@@ -0,0 +1,15 @@
+## configure.in.in for debugger.
+## Use y2tool y2autoconf to get configure.in
+
+## Initialize
+@YAST2-INIT-COMMON@
+@YAST2-INIT-PROGRAM@
+@YAST2-INIT-YCP@
+
+## some common checks
+@YAST2-CHECKS-COMMON@
+@YAST2-CHECKS-PROGRAM@
+@YAST2-CHECKS-YCP@
+
+## and generate the output...
+@YAST2-OUTPUT@
View
1,481 doc/PackageManagement.xml
@@ -0,0 +1,1481 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "/usr/share/sgml/db41xml/docbookx.dtd"
+[
+<!ENTITY version "0.01">
+<!ENTITY megacopy "MEGACOPYRIGHT &copy;&reg;">
+]>
+
+<book>
+
+ <bookinfo>
+ <title>SuSE Package Management</title>
+ <subtitle>Specification and Implementation</subtitle>
+ <author>
+ <firstname>Klaus</firstname>
+ <surname>Kämpf</surname>
+ </author>
+ <copyright><year>2002</year><holder>SuSE Linux AG</holder></copyright>
+ <legalnotice>
+ <para>This document is meant for SuSE internal use only.
+</para>
+ </legalnotice>
+ <abstract>
+ <para>All about package handling in SuSE Linux beyond 8.0
+</para>
+ </abstract>
+ </bookinfo>
+
+
+
+<chapter><title>Motivation</title>
+
+<para>
+The multi-vendor character of 'UnitedLinux' requires the split of
+the single vendor installation media we now have, to a "base media"
+(containing the basic UnitedLinux system) and "product media"
+(containing the product, i.e. an email server application).
+</para>
+<para>
+YaST must be able to handle both medias and resolve (package)
+dependencies between them.
+</para>
+<para>
+This document describes the requirements and implementation
+details of the package handling toolset implemented for
+UnitedLinux.
+</para>
+
+</chapter>
+
+<chapter>
+<title>Requirements</title>
+
+<section><title>2.1 General</title>
+
+<para>
+Handling package dependency resolving across multiple package sources
+is quite complex. Since dependency resolving is performed online while
+the user is viewing/selecting/deselcting packages, it must be reasonably
+fast. This in turn requires memory.
+</para>
+<para>
+Current dependency resolvers (SuSE YaST2, Caldera PHI) require a similar
+amount of resources (ca 15 MB with YaST2 an 2500 package, ca 20 MB with
+PHI and 3500 packages).
+</para>
+<para>
+Dramatic improvements can only be achieved by reducing the number of
+packages (and dependencies).
+</para>
+<para>
+Combining a set of packages to a selection and then computing selection
+dependencies is a possible solution. By handling selections similar
+to packages (selections have a name, a version, and dependencies), the
+same algorithms and similar user interfaces can be used.
+Combining selections to distributions (which equal installation sources)
+are a logical consequence.
+</para>
+<para>
+This all leads to the following:
+<itemizedlist>
+<listitem><para>A set of bytes make a file
+</para></listitem>
+<listitem><para>A set of files make a package
+</para></listitem>
+<listitem><para>A set of packages make a selection
+</para></listitem>
+<listitem><para>A set of selections make a distribution
+</para></listitem>
+</itemizedlist>
+[This leads to having selections as .rpm files and let rpm do all
+the work in finding dependencies. However the selections are only
+a package suggestion and rpms dependencies are too weak to handle
+all cases. Having a selection database besides a package database
+would be a good thing.]
+</para>
+</section>
+
+<section><title>2.2 User Interface</title>
+
+<para>
+The package management must be usable by command line, by a text (curses)
+interface, and by a graphical (X11) frontend.
+Detailed functional requirements (use-cases) are listed below.
+</para>
+
+</section>
+<section><title>2.3 Installation Media</title>
+
+<para>
+The concept of separated base and product CDs can be extended to a
+variety of medias (CD, FTP, NFS, HTTP, ...) and contents (patch CD,
+maintenance web server, network installation server, etc.)
+</para>
+<para>
+Each media is named an <emphasis>Installation Source</emphasis>, since it's independant
+from it's physical representation (CD, DVD, Network, ...).
+</para>
+
+<para>
+Such an installation source must contain
+<itemizedlist>
+ <listitem><para>A media identifier
+ To cleary (re-)identify a (known) medium
+ </para></listitem>
+ <listitem><para>A content description
+ To show the user media information
+ </para></listitem>
+ <listitem><para>Further information (Vendor, Version, License, Architecture, ...)
+ As a more detailed media description for the user.
+ </para></listitem>
+ <listitem><para>Selections
+ As a means to reduce complexity as mentioned above.
+ </para></listitem>
+ <listitem><para>Packages
+ The installable data.
+ </para></listitem>
+</itemizedlist>
+</para>
+
+<para>
+In addition to that, an installation source should contain:
+</para>
+
+
+<itemizedlist>
+<listitem><para>
+Package descriptions - technical data as well as textual descriptions for
+all packages - as a cache for instant access to that information which
+otherwise may be accessible only at a remote location with considerable access
+times.
+</para></listitem>
+</itemizedlist>
+
+
+<para>
+Integrating separate 'package sources' into the installer and doing
+cross-media dependency resolving does have a lot of advantages:
+<itemizedlist>
+<listitem><para>Close interaction with SuSE installer
+</para></listitem>
+<listitem><para>Distributed installation (CD, DVD, NFS, ...)
+</para></listitem>
+<listitem><para>Abstracting from physical medium
+</para></listitem>
+<listitem><para>Overlaying package sources eases (online) updates or architecture
+ specific packages (i.e. i686 optimized)
+</para></listitem>
+<listitem><para>an installation source might not be available (i.e. network
+ server down)
+</para></listitem>
+<listitem><para>an installation source might be provided by a different
+ vendor (not SuSE)
+</para></listitem>
+<listitem><para>an installation source might be unreliable (bad MD5)
+</para></listitem>
+<listitem><para>cost of accessing an installation source
+</para></listitem>
+</itemizedlist>
+</para>
+
+<para>
+If an installation media cannot be accessed, the user must have
+the possibility of changing the media (i.e. ftp server, nfs path)
+temporarely.
+</para>
+
+</section>
+<section><title>2.4 Installation Target</title>
+
+<para>
+All package handling is always based on a single installation target,
+the system being administered.
+The target might be remote from the package management, esp. considering
+embedded systems with limited resources for a full dependency handling.
+</para>
+<para>
+Further requirements are:
+<itemizedlist>
+<listitem><para>Keep system consitent all the time.
+</para></listitem>
+<listitem><para>Install package from any source.
+</para></listitem>
+<listitem><para>Switch installation sources dynamically.
+</para></listitem>
+<listitem><para>Control RPM parameters (i.e. --oldpackage, --excludedocs)
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>2.5 Dependency Solving</title>
+
+<para>
+The current package handling is based on the package name only and does not
+take the package version into account. This binds vendor packages
+to a specific distribution.
+</para>
+<para>
+The multiple installation media concept introduces new solver
+requirements since multiple sources can provide the same package (name)
+with identical or different versions, dependencies, architectures.
+This introduces a new level of complexity, as the package name
+is no longer the only differentiating criterium for the solver.
+Esp. dependencies (and conflicts) between different installation media
+must be handled.
+</para>
+<para>
+Having more detailed package dependencies opens up a new set of
+packaging possibilities:
+<itemizedlist>
+<listitem><para>a package might be provided in several versions, user can choose
+ 'best' package (matching his application)
+</para></listitem>
+<listitem><para>easier up/downgrade of packages
+</para></listitem>
+<listitem><para>easier handling of patches (incl. removal of patches)
+</para></listitem>
+<listitem><para>Control dependency solving (i.e. switch it off)
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>2.6 Selections</title>
+
+<para>
+Selections are a means to reduce dependency complexity and to
+group packages to functional blocks, thereby making it easier
+to the customer to choose the right setup.
+Selections are package list which contain including (to be added)
+and excluding (to be removed) packages.
+Selections also define dependencies (requirements, conflicts). By
+adding version information also update complexity can be reduced.
+</para>
+
+</section>
+<section><title>2.7 Packages</title>
+
+<para>
+A package is the smallest entity handled by the package management.
+Packages consist of
+<itemizedlist>
+<listitem><para>A name
+</para></listitem>
+<listitem><para>A version
+</para></listitem>
+<listitem><para>An architecture
+</para></listitem>
+<listitem><para>Dependencies
+</para></listitem>
+<listitem><para>Files
+</para></listitem>
+<listitem><para>Attributes (Label, Size, Group Tag, ...)
+</para></listitem>
+</itemizedlist>
+</para>
+
+<remark>see also ~sh/y2-proto/sw-single/sw-single-spec.txt </remark>
+
+</section>
+<section><title>2.8 Patches</title>
+
+<para>
+Patches describe changes to be made to a system.
+A patch consists of
+<itemizedlist>
+<listitem><para>A name
+</para></listitem>
+<listitem><para>A version
+</para></listitem>
+<listitem><para>An architecture
+</para></listitem>
+<listitem><para>Dependencies
+</para></listitem>
+<listitem><para>Attributes
+</para></listitem>
+<listitem><para>Text, Packages, Scripts
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>2.9 Update</title>
+
+<para>
+Things to consider for an update are:
+<itemizedlist>
+<listitem><para>A functionality (Requires-Tag) might be provided by several
+packages. Decide which one to choose.
+</para></listitem>
+<listitem><para>Package renames
+</para></listitem>
+<listitem><para>Package splits
+</para></listitem>
+<listitem><para>Package drops
+</para></listitem>
+<listitem><para>Package unknown (foreign package) with dependencies
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+</chapter>
+
+<chapter><title>Use Cases</title>
+
+<section><title>3.1 Installation media</title>
+
+<para>
+Installation media functions are:
+<itemizedlist>
+<listitem><para>List known media
+</para></listitem>
+<listitem><para>Add a new media
+</para></listitem>
+<listitem><para>Edit a media entry
+e.g. Server changed, login changed, ranking
+</para></listitem>
+<listitem><para>Check media
+MD5 sums, integrety checks
+</para></listitem>
+<listitem><para>Delete a media
+</para></listitem>
+<listitem><para>Temporarely disable/enable a media
+</para></listitem>
+<listitem><para>View media information
+(Content, Selections, Packages, etc.)
+</para></listitem>
+</itemizedlist>
+</para>
+
+
+</section>
+<section><title>3.2 Selections</title>
+
+<para>
+Selection based functions are:
+<itemizedlist>
+<listitem><para>View selection
+Files, Dependencies, Attributes
+</para></listitem>
+<listitem><para>Show installed selections (0...100%)
+</para></listitem>
+<listitem><para>Add selection
+</para></listitem>
+<listitem><para>Delete selection
+</para></listitem>
+<listitem><para>Create/Save selection
+</para></listitem>
+<listitem><para>Load selection
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>3.3 Packages</title>
+
+<para>
+Package based functions are:
+<itemizedlist>
+<listitem><para>View package
+Author, License, Files, Provides, Requires, Conflicts, Label, Version,
+ Architecture
+</para></listitem>
+<listitem><para>Add package
+with/without immediate dependency/size checking
+</para></listitem>
+<listitem><para>Delete package
+with/without immediate dependency/size checking
+</para></listitem>
+</itemizedlist>
+</para>
+
+
+</section>
+<section><title>3.4 Dependency Solving</title>
+
+<para>
+Solver use cases are:
+<itemizedlist>
+<listitem><para>What-if view
+</para></listitem>
+<listitem><para>Or dependencies
+multiple packages providing the same requirement
+</para></listitem>
+<listitem><para>Conflict handling
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>3.5 Packages</title>
+
+<para>
+Package based functions are:
+<itemizedlist>
+<listitem><para>Package info in selected language
+</para></listitem>
+<listitem><para>Query for packages
+</para></listitem>
+<listitem><para>Select package
+</para></listitem>
+<listitem><para>Deselect package
+</para></listitem>
+<listitem><para>Remove package
+</para></listitem>
+<listitem><para>Update package
+</para></listitem>
+<listitem><para>View package information
+Label, Files, Size, Dependencies, Architecture, Installation Source, Vendor
+</para></listitem>
+</itemizedlist>
+</para>
+<para>
+Further package related use cases see <ulink url="#UserInterface">User Interface</ulink> chapter.
+</para>
+
+</section>
+<section><title>3.6 Patches</title>
+
+<para>
+Patch based functions are:
+<itemizedlist>
+<listitem><para>List installed patches
+</para></listitem>
+<listitem><para>Check if patch applies
+</para></listitem>
+<listitem><para>Check if patch installed
+</para></listitem>
+<listitem><para>Check patch dependencies
+</para></listitem>
+<listitem><para>Delete patch
+</para></listitem>
+<listitem><para>Update patch
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+</chapter>
+<chapter><title>User Interface</title>
+<para>Written by <ulink url="mailto:sh@suse.de">Stefan Hundhammer</ulink></para>
+
+<section><title>4.1 Views</title>
+<para>
+The user can dynamically switch between those views:
+<itemizedlist>
+<listitem><para>Add-on selections view (devlopment, multimedia, games, ...)
+ The user can add or remove any number of them.
+</para></listitem>
+<listitem><para>RPM group tags view
+ The RPM group tags are displayed as a tree.
+ The corresponding packages are displayed as a list when a leaf in that tree
+ is selected.
+</para></listitem>
+<listitem><para>Package search view
+ Search form like in current YaST2:
+ Search for pkg name, in pkg descriptions
+</para></listitem>
+</itemizedlist>
+</para>
+<para>
+The old base selections are just a special case of the system base plus
+some predefined add-on selections, so there will be no exactly-one-out-of-n
+choice of base selections (formerly "default", "default+office", "minimal",
+etc.).
+</para>
+
+
+</section>
+<section><title>4.2 Package list</title>
+<para>
+In most views (at least for the RPM group tags view and for the pkg search
+view) a list of packages is displayed:
+</para>
+<para>
+For each pkg, the following fields are displayed in the list:
+<itemizedlist>
+ <listitem><para>pkg selection status
+ <itemizedlist>
+ <listitem><para>for fresh installation:
+ <itemizedlist>
+ <listitem><para>[ ] not selected
+ </para></listitem>
+ <listitem><para>[x] manually selected
+ </para></listitem>
+ <listitem><para>[a] automatically selected because of dependencies
+ </para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>
+ for update:
+ <itemizedlist>
+ <listitem><para>[ ] currently not installed, will not be installed
+ </para></listitem>
+ <listitem><para>[i] installed, keep that version
+ </para></listitem>
+ <listitem><para>[u] update to newer version
+ </para></listitem>
+ <listitem><para>[d] delete
+ </para></listitem>
+ <listitem><para>[r] pkg renamed - the user cannot select this state. This is for cases
+ where a new pkg (whith a new name) replaced an existing one.
+ </para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem><para>pkg versions - at least current (if pkg already installed) and preferred.
+ The installation sources may contain any number of instances of the same
+ pkg. The backend automatically selects the "preferred" version according to
+ the installation source ranking.
+ </para></listitem>
+</itemizedlist>
+</para>
+<para>
+Other pkg attributes like:</para>
+<itemizedlist>
+<listitem><para>pkg name</para></listitem>
+<listitem><para>pkg size</para></listitem>
+<listitem><para>pkg short description</para></listitem>
+</itemizedlist>
+<para>
+and maybe more.
+</para>
+
+
+</section>
+<section><title>4.3 Package details</title>
+
+<para>
+If screen space permits, detailed information about the current pkg is
+displayed. If screen space is limited, the same information is displayed upon
+user request (button press / key press).
+</para>
+<para>
+In the simplest version, all the information in those views corresponds to the
+"preferred" version of the current pkg. Advanced (optional) versions may allow
+to switch from one version to another.
+</para>
+<para>
+
+Pkg details views:
+<itemizedlist>
+<listitem><para>Pkg long description. Both plain text and (simple - QSimpleRichText) HTML are
+ supported. If the user interface supports displaying images, images are
+ supported, too (screen shots etc.).
+</para></listitem>
+<listitem><para>Technical data
+ The data "rpm -qi" provides (minus the pkg long description), e.g.
+ pkg name, version, license, home page, source RPM, buld date, ...
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>4.4 Actions</title>
+
+<para>
+<itemizedlist>
+<listitem><para>Cycle pkg selectionmultiple clicks may be required to
+ switch from the curent state to the one desired
+</para></listitem>
+<listitem><para>Show pkg details description (if not already present on screen)
+</para></listitem>
+
+<listitem><para>Start pkg search (if pkg search view is selected)
+ <itemizedlist>
+ <listitem><para>search for pkg name
+</para></listitem>
+ <listitem><para>full-text search in pkg description
+</para></listitem>
+ <listitem><para>toggle case sensitive search
+</para></listitem>
+ </itemizedlist>
+</para></listitem>
+<listitem><para>Save / load settings
+</para></listitem>
+
+<listitem><para>Toggle immediate dependency check
+</para></listitem>
+
+<listitem><para>Check dependencies
+</para></listitem>
+
+
+<listitem><para>Advanced (optional):
+<itemizedlist>
+<listitem><para>Select all
+</para></listitem>
+<listitem><para>Deselect all
+</para></listitem>
+<listitem><para>Delete all
+</para></listitem>
+<listitem><para>Delete nothing
+</para></listitem>
+<listitem><para>Replace all
+</para></listitem>
+<listitem><para>Replace nothing
+</para></listitem>
+<listitem><para>Don't replace anything, delete instead
+</para></listitem>
+<listitem><para>Replace, don't delete
+</para></listitem>
+</itemizedlist>
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>4.5 Add-on Features 1 - Recommended</title>
+
+<para>
+<itemizedlist>
+<listitem><para>New selection status for each pkg: "taboo"
+
+ This excludes a pkg from automatic selection via dependencies - dependency
+ conflict warnings will be issued instead. This way a user could make sure he
+ doesn't get a specific package under any circumstances, in particular not
+ through the back door via automatic dependency solving. Many sysadmins might
+ be grateful for that: Set "xlibs" to "taboo" and make sure the new server
+ doesn't get any part of X or KDE installed.
+ <emphasis>
+ ma+lnussel say:
+ This is easy to implement in the backend if the requirement is included in
+ the basic design.
+
+ sh: For the frontend, it's trivial.
+ </emphasis>
+</para></listitem>
+<listitem><para>New pkg status "don't touch"for pkgs the user doesn't want to be updated
+ or deleted in any case, such as pkgs he builds manually or gets from some
+ other source.
+</para></listitem>
+<listitem><para>New view for current pkg: Conflicts
+
+ Displays a list of pkgs this pkg conflicts with.
+</para></listitem>
+<listitem><para>New view for current pkg: Requires
+
+ Displays a flat list of pkgs required by the current pkg along with
+ indications which of those are already automatically selected anyway and
+ which ones would be added by adding this pkg - plus the accumulated size of
+ those new pkgs.
+</para></listitem>
+<listitem><para>New view for current pkg: Required by
+
+ Displays a flat list of pkgs that require this pkg.
+</para></listitem>
+</itemizedlist>
+</para>
+
+
+</section>
+<section><title>4.6 Add-on Features 2 - Very useful</title>
+
+<para>
+<itemizedlist>
+<listitem><para>New view for current pkg: File list
+
+ Displays a list of files this pkg contains (rpm -qpl).
+ This might require the installation medium the RPM is on to be inserted.
+</para></listitem>
+
+
+<listitem><para>Tools for direct status change without cycling through all possible values.
+
+ The Qt UI should get tool buttons like in paint programs GIMP, CorelDraw
+ etc. that directly set the pkg state to a defined value. The mouse cursor
+ will change to indicate that - e.g. an arrow with a trash can to mark pkgs
+ for deletion with one click etc.
+
+ The NCurses UI should get one-character shortcuts to do the same - e.g. "i"
+ for "install", "d" for delete etc.
+
+ Cycling through all possible values more often than not sets intermediate
+ states which cause unnecessary problems.
+</para></listitem>
+
+<listitem><para>Context menu for directly setting the pkg status
+</para></listitem>
+
+<listitem><para>Qt UI: Tool tips (balloon help) for different versions of the same pkg
+ Display more info than just "V7.32" in column "CD" - e.g.
+<screen width="80">
+ V 7.32 from SuSE Firewall Update CD
+ 283k
+</screen>
+</para></listitem>
+
+<listitem><para>What if... - shows list of pkgs that will be installed, deleted, updated
+</para></listitem>
+</itemizedlist>
+</para>
+
+
+</section>
+<section><title>4.7 Add-on Features 3 - Useful</title>
+
+<para>
+<itemizedlist>
+<listitem><para>New view for current pkg: Versions per installation source
+
+ Improved summary of all instances of the current pkg on all available
+ installation sources, e.g.
+<screen width="80">
+ V 7.32 SuSE Firewall Update CD - 283k
+ V 7.30 SuSE Firewall CD - 257k
+ V 6.0 UBL 1.0 Base CD - 180k
+</screen>
+</para></listitem>
+
+<listitem><para>New view for pkg list: Supported MIME types
+
+ Instead of the RPM group tags, display known MIME types and list pkgs that
+ can handle the selected ones: Which pkgs support .png, which support MS Word
+ .doc etc.
+
+ The information is there - SuSE-WM already uses it.
+</para></listitem>
+
+
+<listitem><para>New view for pkg list: Supported hardware
+
+ Similar to above: Which pkgs support CD recorders, sound cards etc.
+</para></listitem>
+
+
+<listitem><para>Save status of SW selection window: Current view etc.
+</para></listitem>
+
+
+<listitem><para>Pkg view: Replaced / obsoleted pkgs
+ Show a list of pkgs that are replaced by other pkgs.
+</para></listitem>
+
+
+<listitem><para>New view for pkg list: Licenses
+ (suggested by ke on [research] on 2002-05-22)
+ View packages by license type: GPL, BSD, ...
+
+ Maybe this should rather be a filter that works on top of other views.
+ Otherwise we'd get too many pkgs in each category: Most pkgs (70%? 80%?) are GPL.
+</para></listitem>
+</itemizedlist>
+</para>
+
+</section>
+<section><title>4.8 Add-on Features 4 - Nice to have</title>
+
+<para>
+<itemizedlist>
+<listitem><para>New view for current pkg: Change log
+
+ Displays this pkg's change log.
+ This might require the installation medium the RPM is on to be inserted.
+</para></listitem>
+
+<listitem><para>Icons in the pkg list to indicate the type of pkg (system, X, KDE, ...)
+