summaryrefslogtreecommitdiffstats
path: root/perl-install/standalone/po/id.po
diff options
context:
space:
mode:
authorThierry Vignaud <tv@mandriva.org>2008-02-14 12:02:41 +0000
committerThierry Vignaud <tv@mandriva.org>2008-02-14 12:02:41 +0000
commit884ee8cb70e50b8da4a4dcf52b97300576348f55 (patch)
treec0e629bf339419b5a5c95ddc04c3ee1a09215da6 /perl-install/standalone/po/id.po
parentbea0572b226aed46429ae65276cc84cae8f31720 (diff)
downloaddrakx-884ee8cb70e50b8da4a4dcf52b97300576348f55.tar
drakx-884ee8cb70e50b8da4a4dcf52b97300576348f55.tar.gz
drakx-884ee8cb70e50b8da4a4dcf52b97300576348f55.tar.bz2
drakx-884ee8cb70e50b8da4a4dcf52b97300576348f55.tar.xz
drakx-884ee8cb70e50b8da4a4dcf52b97300576348f55.zip
sync with code
Diffstat (limited to 'perl-install/standalone/po/id.po')
-rw-r--r--perl-install/standalone/po/id.po179
1 files changed, 98 insertions, 81 deletions
diff --git a/perl-install/standalone/po/id.po b/perl-install/standalone/po/id.po
index 1c8b0701a..fe61f05ab 100644
--- a/perl-install/standalone/po/id.po
+++ b/perl-install/standalone/po/id.po
@@ -16,7 +16,7 @@ msgid ""
msgstr ""
"Project-Id-Version: DrakX 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-01-17 14:33+0100\n"
+"POT-Creation-Date: 2008-02-14 13:01+0100\n"
"PO-Revision-Date: 2007-10-27 19:35+0700\n"
"Last-Translator: Willy Sudiarto Raharjo <willysr@gmail.com>\n"
"Language-Team: Indonesia <mdk-id@yahoogroups.com>\n"
@@ -73,7 +73,7 @@ msgstr "Detail"
msgid "Silent"
msgstr "Sederhana"
-#: drakboot:132 drakfont:693 drakperm:378 drakperm:388 drakups:27
+#: drakboot:132 drakbug:233 drakfont:693 drakperm:375 drakperm:385 drakups:27
#: harddrake2:515 localedrake:43 scannerdrake:51 scannerdrake:54
#: scannerdrake:297 scannerdrake:302 scannerdrake:955
#, c-format
@@ -179,67 +179,67 @@ msgstr ""
"dibawah.\n"
"Pastikan kartu video Anda mendukung mode yang Anda pilih."
-#: drakbug:64 drakbug:136
+#: drakbug:65 drakbug:143
#, c-format
msgid "The \"%s\" program has crashed with the following error:"
msgstr "Program \"%s\" crash dengan kesalahan berikut:"
-#: drakbug:75
+#: drakbug:76
#, c-format
msgid "Mandriva Linux Bug Report Tool"
msgstr "Aplikasi Pelapor Kesalahan Mandriva Linux"
-#: drakbug:80
+#: drakbug:81
#, c-format
msgid "Mandriva Linux Control Center"
msgstr "Pusat Kontrol Mandriva Linux"
-#: drakbug:81
+#: drakbug:82
#, c-format
msgid "First Time Wizard"
msgstr "Wizard Pertama"
-#: drakbug:82
+#: drakbug:83
#, c-format
msgid "Synchronization tool"
msgstr "Aplikasi Sinkronisasi"
-#: drakbug:83 drakbug:222
+#: drakbug:84 drakbug:195
#, c-format
msgid "Standalone Tools"
msgstr "Aplikasi Mandiri"
-#: drakbug:85 drakbug:86
+#: drakbug:86 drakbug:87
#, c-format
msgid "Mandriva Online"
msgstr "Mandriva Online"
-#: drakbug:87
+#: drakbug:88
#, c-format
msgid "Remote Control"
msgstr "Kontrol Remote"
-#: drakbug:88
+#: drakbug:89
#, c-format
msgid "Software Manager"
msgstr "Manajer Perangkat Lunak"
-#: drakbug:89
+#: drakbug:90
#, c-format
msgid "Windows Migration tool"
msgstr "Aplikasi Migrasi Windows"
-#: drakbug:90
+#: drakbug:91
#, c-format
msgid "Configuration Wizards"
msgstr "Wizard Konfigurasi"
-#: drakbug:112
+#: drakbug:113
#, c-format
msgid "Select Mandriva Tool:"
msgstr "Pilih Aplikasi Mandriva:"
-#: drakbug:113
+#: drakbug:114
#, c-format
msgid ""
"or Application Name\n"
@@ -248,32 +248,32 @@ msgstr ""
"atau Nama Aplikasi\n"
"(atau Path Lengkap):"
-#: drakbug:116
+#: drakbug:117
#, c-format
msgid "Find Package"
msgstr "Cari Paket"
-#: drakbug:118
+#: drakbug:119
#, c-format
msgid "Package: "
msgstr "Paket: "
-#: drakbug:119
+#: drakbug:120
#, c-format
msgid "Kernel:"
msgstr "Kernel:"
-#: drakbug:135
+#: drakbug:142
#, fuzzy, c-format
msgid "The \"%s\" program has segfaulted with the following error:"
msgstr "Program \"%s\" crash dengan kesalahan berikut:"
-#: drakbug:145
+#: drakbug:146
#, c-format
msgid "Its gdb trace is:"
msgstr ""
-#: drakbug:153
+#: drakbug:149
#, c-format
msgid ""
"To submit a bug report, click on the report button. \n"
@@ -288,31 +288,48 @@ msgstr ""
"Informasi penting yang harus disertakan pada laporan Anda termasuk hasil "
"output lspcidrake -v, versi kernel, dan /proc/cpuinfo."
-#: drakbug:161 drakperm:134 draksec:438 draksec:440 draksec:459 draksec:461
+#: drakbug:152
+#, c-format
+msgid "Please describe what you were doing when it crashed:"
+msgstr ""
+
+#: drakbug:164 drakperm:135 draksec:438 draksec:440 draksec:459 draksec:461
#, c-format
msgid "Help"
msgstr "Bantuan"
-#: drakbug:163
+#: drakbug:168
#, c-format
msgid "Report"
msgstr "Laporan"
-#: drakbug:196 drakfont:517
+#: drakbug:169 drakfont:517
#, c-format
msgid "Close"
msgstr "Tutup"
-#: drakbug:232
+#: drakbug:202
#, c-format
msgid "Not installed"
msgstr "Tidak terinstall"
-#: drakbug:245
+#: drakbug:215
#, c-format
msgid "Package not installed"
msgstr "Paket tidak terinstall"
+#: drakbug:234
+#, c-format
+msgid ""
+"You must type in what you were doing when this bug happens in order to "
+"increase the reproductibility of this bug and the odds of fixing it"
+msgstr ""
+
+#: drakbug:235
+#, c-format
+msgid "Thanks."
+msgstr ""
+
#: drakclock:30 draksec:334
#, c-format
msgid "Date, Clock & Time Zone Settings"
@@ -804,62 +821,62 @@ msgstr "Pusat Bantuan Mandriva Linux"
msgid "No Help entry for %s\n"
msgstr "Tidak ada daftar bantuan untuk %s\n"
-#: drakperm:22
+#: drakperm:23
#, c-format
msgid "System settings"
msgstr "Setting sistem"
-#: drakperm:23
+#: drakperm:24
#, c-format
msgid "Custom settings"
msgstr "Setting kebiasaan"
-#: drakperm:24
+#: drakperm:25
#, c-format
msgid "Custom & system settings"
msgstr "Setting kebiasaan & sistem"
-#: drakperm:32
+#: drakperm:33
#, c-format
msgid "Security Permissions"
msgstr "Ijin Keamanan"
-#: drakperm:44
+#: drakperm:45
#, c-format
msgid "Editable"
msgstr "Bisa diedit"
-#: drakperm:49 drakperm:322
+#: drakperm:50 drakperm:319
#, c-format
msgid "Path"
msgstr "Path"
-#: drakperm:49 drakperm:250
+#: drakperm:50 drakperm:248
#, c-format
msgid "User"
msgstr "Pengguna"
-#: drakperm:49 drakperm:250
+#: drakperm:50 drakperm:248
#, c-format
msgid "Group"
msgstr "Grup"
-#: drakperm:49 drakperm:334
+#: drakperm:50 drakperm:331
#, c-format
msgid "Permissions"
msgstr "Izin"
-#: drakperm:59
+#: drakperm:60
#, c-format
msgid "Add a new rule"
msgstr "Tambahkan aturan baru"
-#: drakperm:66 drakperm:101 drakperm:126
+#: drakperm:67 drakperm:102 drakperm:127
#, c-format
msgid "Edit current rule"
msgstr "Edit aturan aktual"
-#: drakperm:108
+#: drakperm:109
#, c-format
msgid ""
"Here you can see files to use in order to fix permissions, owners, and "
@@ -870,7 +887,7 @@ msgstr ""
"pengguna, dan grup via msec.\n"
"Anda juga bisa mengedit aturan Anda yang akan menimpa aturan default."
-#: drakperm:110
+#: drakperm:111
#, c-format
msgid ""
"The current security level is %s.\n"
@@ -879,115 +896,115 @@ msgstr ""
"Level keamanan aktual adalah %s.\n"
"Pilih izin untuk melihat/mengedit"
-#: drakperm:122
+#: drakperm:123
#, c-format
msgid "Up"
msgstr "Naik"
-#: drakperm:122
+#: drakperm:123
#, c-format
msgid "Move selected rule up one level"
msgstr "Geser aturan terpilih satu level keatas"
-#: drakperm:123
+#: drakperm:124
#, c-format
msgid "Down"
msgstr "Turun"
-#: drakperm:123
+#: drakperm:124
#, c-format
msgid "Move selected rule down one level"
msgstr "Geser aturan terpilih satu level kebawah"
-#: drakperm:124
+#: drakperm:125
#, c-format
msgid "Add a rule"
msgstr "Tambah aturan"
-#: drakperm:124
+#: drakperm:125
#, c-format
msgid "Add a new rule at the end"
msgstr "Tambah aturan baru di akhir"
-#: drakperm:125
+#: drakperm:126
#, c-format
msgid "Delete"
msgstr "Hapus"
-#: drakperm:125
+#: drakperm:126
#, c-format
msgid "Delete selected rule"
msgstr "Hapus aturan terpilih"
-#: drakperm:126 drakups:300 drakups:362 drakups:382
+#: drakperm:127 drakups:300 drakups:362 drakups:382
#, c-format
msgid "Edit"
msgstr "Edit"
-#: drakperm:242
+#: drakperm:240
#, c-format
msgid "browse"
msgstr "jelajah"
-#: drakperm:247
+#: drakperm:245
#, c-format
msgid "user"
msgstr "Pemakai"
-#: drakperm:247
+#: drakperm:245
#, c-format
msgid "group"
msgstr "kelompok"
-#: drakperm:247
+#: drakperm:245
#, c-format
msgid "other"
msgstr "lainnya"
-#: drakperm:250
+#: drakperm:248
#, c-format
msgid "Other"
msgstr "Lainnya"
-#: drakperm:252
+#: drakperm:250
#, c-format
msgid "Read"
msgstr "Baca"
#. -PO: here %s will be either "user", "group" or "other"
-#: drakperm:255
+#: drakperm:253
#, c-format
msgid "Enable \"%s\" to read the file"
msgstr "Izinkan \"%s\" untuk membaca file"
-#: drakperm:259
+#: drakperm:257
#, c-format
msgid "Write"
msgstr "Tulis"
#. -PO: here %s will be either "user", "group" or "other"
-#: drakperm:262
+#: drakperm:260
#, c-format
msgid "Enable \"%s\" to write the file"
msgstr "Izinkan \"%s\" untuk menulis file"
-#: drakperm:266
+#: drakperm:264
#, c-format
msgid "Execute"
msgstr "Eksekusi"
#. -PO: here %s will be either "user", "group" or "other"
-#: drakperm:269
+#: drakperm:267
#, c-format
msgid "Enable \"%s\" to execute the file"
msgstr "Izinkan \"%s\" untuk eksekusi file"
-#: drakperm:272
+#: drakperm:270
#, c-format
msgid "Sticky-bit"
msgstr "Sticky-bit"
-#: drakperm:272
+#: drakperm:270
#, c-format
msgid ""
"Used for directory:\n"
@@ -996,57 +1013,57 @@ msgstr ""
"Digunakan untuk direktori:\n"
" hanya pemilik direktori atau file pada direktori ini yang dapat menghapusnya"
-#: drakperm:273
+#: drakperm:271
#, c-format
msgid "Set-UID"
msgstr "Set-UID"
-#: drakperm:273
+#: drakperm:271
#, c-format
msgid "Use owner id for execution"
msgstr "Gunakan id pemilik untuk eksekusi"
-#: drakperm:274
+#: drakperm:272
#, c-format
msgid "Set-GID"
msgstr "Set-GID"
-#: drakperm:274
+#: drakperm:272
#, c-format
msgid "Use group id for execution"
msgstr "Gunakan id grup untuk eksekusi"
-#: drakperm:292
+#: drakperm:289
#, c-format
msgid "User:"
msgstr "Pengguna :"
-#: drakperm:293
+#: drakperm:290
#, c-format
msgid "Group:"
msgstr "Grup:"
-#: drakperm:297
+#: drakperm:294
#, c-format
msgid "Current user"
msgstr "Pengguna aktual"
-#: drakperm:298
+#: drakperm:295
#, c-format
msgid "When checked, owner and group will not be changed"
msgstr "Jika dipilih, pemilik dan grup tidak akan diubah"
-#: drakperm:308
+#: drakperm:305
#, c-format
msgid "Path selection"
msgstr "Pilihan path"
-#: drakperm:328
+#: drakperm:325
#, c-format
msgid "Property"
msgstr "Properti"
-#: drakperm:378
+#: drakperm:375
#, c-format
msgid ""
"The first character of the path must be a slash (\"/\"):\n"
@@ -1055,17 +1072,17 @@ msgstr ""
"Karakter pertama dari path harus berupa slash (\"/\"):\n"
"\"%s\""
-#: drakperm:388
+#: drakperm:385
#, c-format
msgid "Both the username and the group must valid!"
msgstr "Nama pengguna dan grup harus valid!"
-#: drakperm:389
+#: drakperm:386
#, c-format
msgid "User: %s"
msgstr "Pengguna: %s"
-#: drakperm:390
+#: drakperm:387
#, c-format
msgid "Group: %s"
msgstr "Grup: %s"
@@ -1097,7 +1114,7 @@ msgstr "Abaikan"
#: draksec:72 drakups:99 harddrake2:369 scannerdrake:66 scannerdrake:70
#: scannerdrake:78 scannerdrake:319 scannerdrake:368 scannerdrake:505
-#: scannerdrake:509 scannerdrake:531 service_harddrake:252
+#: scannerdrake:509 scannerdrake:531 service_harddrake:253
#, c-format
msgid "Please wait"
msgstr "Harap tunggu"
@@ -3586,27 +3603,27 @@ msgstr "Scanner Anda tidak akan tersedia pada jaringan."
msgid "Could not install the packages needed to share your scanner(s)."
msgstr "Tidak bisa menginstall paket yang diperlukan untuk berbagi scanner."
-#: service_harddrake:124
+#: service_harddrake:125
#, c-format
msgid "Some devices in the \"%s\" hardware class were removed:\n"
msgstr "Beberapa perangkat pada kelas perangkat keras \"%s\" dihapus:\n"
-#: service_harddrake:125
+#: service_harddrake:126
#, c-format
msgid "- %s was removed\n"
msgstr "- %s telah dihapus\n"
-#: service_harddrake:128
+#: service_harddrake:129
#, c-format
msgid "Some devices were added: %s\n"
msgstr "Beberapa perangkat ditambahkan: %s\n"
-#: service_harddrake:129
+#: service_harddrake:130
#, c-format
msgid "- %s was added\n"
msgstr "- %s telah ditambahkan\n"
-#: service_harddrake:252
+#: service_harddrake:253
#, c-format
msgid "Hardware probing in progress"
msgstr "Pendeteksian perangkat keras sedang berjalan"
a> 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
package pkgs; # $Id$

use diagnostics;
use strict;
use vars qw(*LOG %compssListDesc @skip_list %by_lang @preferred $limitMinTrans $PKGS_SELECTED $PKGS_FORCE $PKGS_INSTALLED $PKGS_BASE $PKGS_SKIP $PKGS_UPGRADE);

use common qw(:common :file :functional);
use install_any;
use commands;
use run_program;
use log;
use pkgs;
use fs;
use loopback;
use lang;
use c;

#- lower bound on the left ( aka 90 means [90-100[ )
%compssListDesc = (
 100 => __("mandatory"), #- do not use it, it's for base packages
  90 => __("must have"), #- every install have these packages (unless hand de-selected in expert, or not enough room)
  80 => __("important"), #- every beginner/custom install have these packages (unless not enough space)
		         #- has minimum X install (XFree86 + icewm)(normal)
  70 => __("very nice"), #- KDE(normal)
  60 => __("nice"),      #- gnome(normal)
  50 => __("interesting"),
  40 => __("interesting"),
  30 => __("maybe"),
  20 => __("maybe"),
  10 => __("maybe"),#__("useless"),
   0 => __("maybe"),#__("garbage"),
#- if the package requires locales-LANG and LANG is chosen, rating += 90
#- if the package is in %by_lang and the corresponding LANG is chosen, rating += 90   (see %by_lang below)
 -10 => __("i18n (important)"), #- every install in the corresponding lang have these packages
 -20 => __("i18n (very nice)"), #- every beginner/custom install in the corresponding lang have theses packages
 -30 => __("i18n (nice)"),
);
#- HACK: rating += 50 for some packages (like kapm, cf install_any::setPackages)

%by_lang = (
  'ar'	=> [ 'acon' ],
#'be_BE.CP1251' => [ 'fonts-ttf-cyrillic' ],
#'bg_BG' => [ 'fonts-ttf-cyrillic' ],
  'cs'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
# 'cy'  => iso8859-14 fonts
# 'el'	=> greek fonts
# 'eo'	=> iso8859-3 fonts
  'fa'  => [ 'acon' ],
  'he'  => [ 'acon' ],
  'hr'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
  'hu'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
  'hy'	=> [ 'fonts-ttf-armenian' ],
  'ja'	=> [ 'rxvt-CLE', 'fonts-ttf-japanese', 'kterm' ],
# 'ka'	=> georgian fonts
  'ko'	=> [ 'rxvt-CLE', 'fonts-ttf-korean' ],
  'lt'	=> [ 'fonts-type1-baltic' ],
  'lv'	=> [ 'fonts-type1-baltic' ],
  'mi'	=> [ 'fonts-type1-baltic' ],
# 'mk'	=> [ 'fonts-ttf-cyrillic' ],
  'pl'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
  'ro'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
# 'ru'  => [ 'XFree86-cyrillic-fonts', 'fonts-ttf-cyrillic' ],
  'ru'  => [ 'XFree86-cyrillic-fonts' ],
  'ru_RU.KOI8-R' => [ 'XFree86-cyrillic-fonts' ],
  'sk'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
  'sl'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
# 'sp'	=> [ 'fonts-ttf-cyrillic' ],
  'sr'	=> [ 'XFree86-ISO8859-2', 'XFree86-ISO8859-2-75dpi-fonts' ],
# 'th'	=> thai fonts
  'tr'	=> [ 'XFree86-ISO8859-9', 'XFree86-ISO8859-9-75dpi-fonts' ],
#'uk_UA' => [ 'fonts-ttf-cyrillic' ],
# 'vi'	=> vietnamese fonts
  'yi'  => [ 'acon' ],
  'zh'  => [ 'rxvt-CLE', 'taipeifonts', 'fonts-ttf-big5', 'fonts-ttf-gb2312' ],
  'zh_CN.GB2312' => [ 'rxvt-CLE', 'fonts-ttf-gb2312' ],
  'zh_TW.Big5' => [ 'rxvt-CLE', 'taipeifonts', 'fonts-ttf-big5' ],
);

@skip_list = qw(
XFree86-8514 XFree86-AGX XFree86-Mach32 XFree86-Mach64 XFree86-Mach8 XFree86-Mono
XFree86-P9000 XFree86-S3 XFree86-S3V XFree86-SVGA XFree86-W32 XFree86-I128
XFree86-Sun XFree86-SunMono XFree86-Sun24 XFree86-3DLabs
MySQL MySQL_GPL mod_php3 midgard postfix metroess metrotmpl
kernel-linus kernel-secure kernel-BOOT
hackkernel hackkernel-BOOT hackkernel-headers
hackkernel-pcmcia-cs hackkernel-smp hackkernel-smp-fb 
autoirpm autoirpm-icons numlock 
);

@preferred = qw(perl-GTK postfix wu-ftpd ghostscript-X vim-minimal kernel ispell-en);

#- constant for small transaction.
$limitMinTrans = 8;

#- constant for packing flags, see below.
$PKGS_SELECTED  = 0x00ffffff;
$PKGS_FORCE     = 0x01000000;
$PKGS_INSTALLED = 0x02000000;
$PKGS_BASE      = 0x04000000;
$PKGS_SKIP      = 0x08000000;
$PKGS_UPGRADE   = 0x20000000;

#- package to ignore, typically in Application CD.
my %ignoreBadPkg = (
		    'civctp-demo'   => 1,
		    'eus-demo'      => 1,
		    'myth2-demo'    => 1,
		    'heretic2-demo' => 1,
		    'heroes3-demo'  => 1,
		    'rt2-demo'      => 1,
		   );

#- basic methods for extracting informations about packages.
#- to save memory, (name, version, release) are no more stored, they
#- are directly generated from (file).
#- all flags are grouped together into (flags), these includes the
#- following flags : selected, force, installed, base, skip.
#- size and deps are grouped to save memory too and make a much
#- simpler and faster depslist reader, this gets (sizeDeps).
sub packageHeaderFile   { my ($pkg) = @_; $pkg->{file} }
sub packageName         { my ($pkg) = @_; $pkg->{file} =~ /([^\(]*)(?:\([^\)]*\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
sub packageSpecificArch { my ($pkg) = @_; $pkg->{file} =~ /[^\(]*(?:\(([^\)]*)\))?-[^-]+-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
sub packageVersion      { my ($pkg) = @_; $pkg->{file} =~ /.*-([^-]+)-[^-]+/ ? $1 : die "invalid file `$pkg->{file}'" }
sub packageRelease      { my ($pkg) = @_; $pkg->{file} =~ /.*-[^-]+-([^-]+)/ ? $1 : die "invalid file `$pkg->{file}'" }

sub packageSize   { my ($pkg) = @_; to_int($pkg->{sizeDeps}) }
sub packageDepsId { my ($pkg) = @_; split ' ', ($pkg->{sizeDeps} =~ /^\d*\s*(.*)/)[0] }

sub packageFlagSelected  { my ($pkg) = @_; $pkg->{flags} & $PKGS_SELECTED }
sub packageFlagForce     { my ($pkg) = @_; $pkg->{flags} & $PKGS_FORCE }
sub packageFlagInstalled { my ($pkg) = @_; $pkg->{flags} & $PKGS_INSTALLED }
sub packageFlagBase      { my ($pkg) = @_; $pkg->{flags} & $PKGS_BASE }
sub packageFlagSkip      { my ($pkg) = @_; $pkg->{flags} & $PKGS_SKIP }
sub packageFlagUpgrade   { my ($pkg) = @_; $pkg->{flags} & $PKGS_UPGRADE }

sub packageSetFlagSelected  { my ($pkg, $v) = @_; $pkg->{flags} &= ~$PKGS_SELECTED; $pkg->{flags} |= $v & $PKGS_SELECTED; }

sub packageSetFlagForce     { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_FORCE)     : ($pkg->{flags} &= ~$PKGS_FORCE); }
sub packageSetFlagInstalled { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_INSTALLED) : ($pkg->{flags} &= ~$PKGS_INSTALLED); }
sub packageSetFlagBase      { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_BASE)      : ($pkg->{flags} &= ~$PKGS_BASE); }
sub packageSetFlagSkip      { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_SKIP)      : ($pkg->{flags} &= ~$PKGS_SKIP); }
sub packageSetFlagUpgrade   { my ($pkg, $v) = @_; $v ? ($pkg->{flags} |= $PKGS_UPGRADE)   : ($pkg->{flags} &= ~$PKGS_UPGRADE); }

sub packageProvides { my ($pkg) = @_; @{$pkg->{provides} || []} }

sub packageFile { 
    my ($pkg) = @_; 
    $pkg->{header} or die "packageFile: missing header";
    $pkg->{file} =~ /([^\(]*)(?:\([^\)]*\))?(-[^-]+-[^-]+)/;
    "$1$2." . c::headerGetEntry($pkg->{header}, 'arch') . ".rpm";
}

sub packageId {
    my ($packages, $pkg) = @_;
    my $i = 0;
    foreach (@{$packages->[1]}) { return $i if $pkg == $packages->[1][$i]; $i++ }
    return;
}

sub cleanHeaders {
    my ($prefix) = @_;
    commands::rm("-rf", "$prefix/tmp/headers") if -e "$prefix/tmp/headers";
}

#- get all headers from an hdlist file.
sub extractHeaders($$$) {
    my ($prefix, $pkgs, $medium) = @_;

    cleanHeaders($prefix);

    run_program::run("packdrake", "-x",
		     "/tmp/$medium->{hdlist}",
		     "$prefix/tmp/headers",
		     map { packageHeaderFile($_) } @$pkgs);

    foreach (@$pkgs) {
	my $f = "$prefix/tmp/headers/". packageHeaderFile($_);
	local *H;
	open H, $f or log::l("unable to open header file $f: $!"), next;
	$_->{header} = c::headerRead(fileno H, 1) or log::l("unable to read header of package ". packageHeaderFile($_));
    }
    @$pkgs = grep { $_->{header} } @$pkgs;
}

#- size and correction size functions for packages.
#- invCorrectSize corrects size in the range 0 to 3Gb approximately, so
#- it should not be used outside these levels.
#- but since it is an inverted parabolic curve starting above 0, we can
#- get a solution where X=Y at approximately 9.3Gb. we use this point as
#- a limit to change the approximation to use a linear one.
#- for information above this point, we have the corrected size below the
#- original size wich is absurd, this point is named D below.
my $A = -121568/100000000000; # -1.21568e-05; #- because perl does like that on some language (TO BE FIXED QUICKLY)
my $B = 121561/100000; # 1.21561
my $C = -239889/10000; # -23.9889 #- doesn't take hdlist's into account as getAvailableSpace will do it.
my $D = (-sqrt(sqr($B - 1) - 4 * $A * $C) - ($B - 1)) / 2 / $A; #- $A is negative so a positive solution is with - sqrt ...
sub correctSize {
    my $csz = ($A * $_[0] + $B) * $_[0] + $C;
    $csz > $_[0] ? $csz : $_[0]; #- size correction (in MB) should be above input argument (as $A is negative).
}
sub invCorrectSize {
    my $sz = $_[0] < $D ? (sqrt(sqr($B) + 4 * $A * ($_[0] - $C)) - $B) / 2 / $A : $_[0];
    $sz < $_[0] ? $sz : $_[0];
}

sub selectedSize {
    my ($packages) = @_;
    my $size = 0;
    foreach (values %{$packages->[0]}) {
	packageFlagSelected($_) && !packageFlagInstalled($_) and $size += packageSize($_) - ($_->{installedCumulSize} || 0);
    }
    $size;
}
sub correctedSelectedSize { correctSize(selectedSize($_[0]) / sqr(1024)) }


#- searching and grouping methods.
#- package is a reference to list that contains
#- a hash to search by name and
#- a list to search by id.
sub packageByName {
    my ($packages, $name) = @_;
    $packages->[0]{$name} or log::l("unknown package `$name'") && undef;
}
sub packageById {
    my ($packages, $id) = @_;
    $packages->[1][$id] or log::l("unknown package id $id") && undef;
}
sub allPackages {
    my ($packages) = @_;
    my %skip_list; @skip_list{@skip_list} = ();
    grep { !exists $skip_list{packageName($_)} } values %{$packages->[0]};
}
sub packagesOfMedium {
    my ($packages, $mediumName) = @_;
    my $medium = $packages->[2]{$mediumName};
    grep { $_->{medium} == $medium } @{$packages->[1]};
}
sub packagesToInstall {
    my ($packages) = @_;
    grep { $_->{medium}{selected} && packageFlagSelected($_) && !packageFlagInstalled($_) } values %{$packages->[0]};
}

sub allMediums {
    my ($packages) = @_;
    keys %{$packages->[2]};
}
sub mediumDescr {
    my ($packages, $medium) = @_;
    $packages->[2]{$medium}{descr};
}

#- selection, unselection of package.
sub selectPackage { #($$;$$$)
    my ($packages, $pkg, $base, $otherOnly, $check_recursion) = @_;

    #- check if the same or better version is installed,
    #- do not select in such case.
    packageFlagInstalled($pkg) and return;

    #- check for medium selection, if the medium has not been
    #- selected, the package cannot be selected.
    $pkg->{medium}{selected} or return;

    #- avoid infinite recursion (mainly against badly generated depslist.ordered).
    $check_recursion ||= {}; exists $check_recursion->{$pkg->{file}} and return; $check_recursion->{$pkg->{file}} = undef;

    #- make sure base package are set even if already selected.
    $base and packageSetFlagBase($pkg, 1);

    #- select package and dependancies, otherOnly may be a reference
    #- to a hash to indicate package that will strictly be selected
    #- when value is true, may be selected when value is false (this
    #- is only used for unselection, not selection)
    unless (packageFlagSelected($pkg)) {
	foreach (packageDepsId($pkg)) {
	    my $preferred;	    
	    if (/\|/) {
		#- choice deps should be reselected recursively as no
		#- closure on them is computed, this code is exactly the
		#- same as pixel's one.
		my %preferred; @preferred{@preferred} = ();
		foreach (split '\|') {
		    my $dep = packageById($packages, $_) or next;
		    $preferred ||= $dep;
		    packageFlagSelected($dep) and $preferred = $dep, last;
		    exists $preferred{packageName($dep)} and $preferred = $dep;
		}
		selectPackage($packages, $preferred, $base, $otherOnly, $check_recursion) if $preferred;
	    } else {
		#- deps have been closed except for choices, so no need to
		#- recursively apply selection, expand base on it.
		my $dep = packageById($packages, $_);
		$base and packageSetFlagBase($dep, 1);
		$otherOnly and !packageFlagSelected($dep) and $otherOnly->{packageName($dep)} = 1;
		$otherOnly or packageSetFlagSelected($dep, 1+packageFlagSelected($dep));
	    }
	}
    }
    $otherOnly and !packageFlagSelected($pkg) and $otherOnly->{packageName($pkg)} = 1;
    $otherOnly or packageSetFlagSelected($pkg, 1+packageFlagSelected($pkg));
    1;
}
sub unselectPackage($$;$) {
    my ($packages, $pkg, $otherOnly) = @_;

    #- base package are not unselectable,
    #- and already unselected package are no more unselectable.
    packageFlagBase($pkg) and return;
    packageFlagSelected($pkg) or return;

    #- dependancies may be used to propose package that may be not
    #- usefull for the user, since their counter is just one and
    #- they are not used any more by other packages.
    #- provides are closed and are taken into account to get possible
    #- unselection of package (value false on otherOnly) or strict
    #- unselection (value true on otherOnly).
    foreach my $provided ($pkg, packageProvides($pkg)) {
	packageFlagBase($provided) and die "a provided package cannot be a base package";
	if (packageFlagSelected($provided)) {
	    my $unselect_alone = 0;
	    foreach (packageDepsId($provided)) {
		if (/\|/) {
		    #- this package use a choice of other package, so we have to check
		    #- if our package is not included in the choice, if this is the
		    #- case, if must be checked one of the other package are selected.
		    foreach (split '\|') {
			my $dep = packageById($packages, $_);
			$dep == $pkg and $unselect_alone |= 1;
			packageFlagBase($dep) || packageFlagSelected($dep) and $unselect_alone |= 2;
		    }
		}
	    }
	    #- provided will not be unselect here if the two conditions are met.
	    $unselect_alone == 3 and next;
	    #- on the other hand, provided package have to be unselected.
	    $otherOnly or packageSetFlagSelected($provided, 0);
	    $otherOnly and $otherOnly->{packageName($provided)} = 1;
	}
	foreach (map { split '\|' } packageDepsId($provided)) {
	    my $dep = packageById($packages, $_);
	    packageFlagBase($dep) and next;
	    packageFlagSelected($dep) or next;
	    for (packageFlagSelected($dep)) {
		$_ == 1 and do { $otherOnly and $otherOnly->{packageName($dep)} ||= 0; };
		$_ >  1 and do { $otherOnly or packageSetFlagSelected($dep, $_-1); };
		last;
	    }
	}
    }
    1;
}
sub togglePackageSelection($$;$) {
    my ($packages, $pkg, $otherOnly) = @_;
    packageFlagSelected($pkg) ? unselectPackage($packages, $pkg, $otherOnly) : selectPackage($packages, $pkg, 0, $otherOnly);
}
sub setPackageSelection($$$) {
    my ($packages, $pkg, $value) = @_;
    $value ? selectPackage($packages, $pkg) : unselectPackage($packages, $pkg);
}

sub unselectAllPackages($) {
    my ($packages) = @_;
    foreach (values %{$packages->[0]}) {
	unless (packageFlagBase($_) || packageFlagUpgrade($_)) {
	    packageSetFlagSelected($_, 0);
	}
    }
}
sub unselectAllPackagesIncludingUpgradable($) {
    my ($packages, $removeUpgradeFlag) = @_;
    foreach (values %{$packages->[0]}) {
	unless (packageFlagBase($_)) {
	    packageSetFlagSelected($_, 0);
	    packageSetFlagUpgrade($_, 0);
	}
    }
}

sub skipSetWithProvides {
    my ($packages, @l) = @_;
    packageSetFlagSkip($_, 1) foreach grep { $_ } map { $_, packageProvides($_) } @l;
}

sub psUpdateHdlistsDeps {
    my ($prefix, $method) = @_;
    my $listf = install_any::getFile('Mandrake/base/hdlists') or die "no hdlists found";

    #- WARNING: this function should be kept in sync with functions
    #- psUsingHdlists and psUsingHdlist.
    #- it purpose it to update hdlist files on system to install.

    #- parse hdlist.list file.
    my $medium = 1;
    foreach (<$listf>) {
	chomp;
	s/\s*#.*$//;
	/^\s*$/ and next;
	m/^\s*(hdlist\S*\.cz2?)\s+(\S+)\s*(.*)$/ or die "invalid hdlist description \"$_\" in hdlists file";
	my ($hdlist, $rpmsdir, $descr) = ($1, $2, $3);

	#- copy hdlist file directly to $prefix/var/lib/urpmi, this will be used
	#- for getting header of package during installation or after by urpmi.
	my $fakemedium = $method . $medium;
	my $newf = "$prefix/var/lib/urpmi/hdlist.$fakemedium.cz2" . ($hdlist =~ /\.cz2/ && "2");
	-e $newf and do { unlink $newf or die "cannot remove $newf: $!"; };
	install_any::getAndSaveFile("Mandrake/base/$hdlist", $newf) or die "no $hdlist found";
	symlinkf $newf, "/tmp/$hdlist";
	++$medium;
    }

    #- this is necessary for urpmi.
    install_any::getAndSaveFile('Mandrake/base/depslist.ordered', "$prefix/var/lib/urpmi/depslist.ordered");
    install_any::getAndSaveFile('Mandrake/base/provides', "$prefix/var/lib/urpmi/provides");
    install_any::getAndSaveFile('Mandrake/base/compss', "$prefix/var/lib/urpmi/compss");
}

sub psUsingHdlists {
    my ($prefix, $method) = @_;
    my $listf = install_any::getFile('Mandrake/base/hdlists') or die "no hdlists found";
    my @packages = ({}, [], {});
    my @hdlists;

    #- parse hdlist.list file.
    my $medium = 1;
    foreach (<$listf>) {
	chomp;
	s/\s*#.*$//;
	/^\s*$/ and next;
	m/^\s*(hdlist\S*\.cz2?)\s+(\S+)\s*(.*)$/ or die "invalid hdlist description \"$_\" in hdlists file";
	push @hdlists, [ $1, $medium, $2, $3 ];
	++$medium;
    }

    foreach (@hdlists) {
	my ($hdlist, $medium, $rpmsdir, $descr) = @$_;

	#- make sure the first medium is always selected!
	#- by default select all image.
	psUsingHdlist($prefix, $method, \@packages, $hdlist, $medium, $rpmsdir, $descr, 1);

    }

    log::l("psUsingHdlists read " . scalar keys(%{$packages[0]}) . " headers on " . scalar keys(%{$packages[2]}) . " hdlists");

    \@packages;
}

sub psUsingHdlist {
    my ($prefix, $method, $packages, $hdlist, $medium, $rpmsdir, $descr, $selected, $fhdlist) = @_;

    #- if the medium already exist, use it.
    $packages->[2]{$medium} and return;

    my $fakemedium = $method . $medium;
    my $m = $packages->[2]{$medium} = { hdlist     => $hdlist,
					medium     => $medium,
					rpmsdir    => $rpmsdir, #- where is RPMS directory.
					descr      => $descr,
					fakemedium => $fakemedium,
					min        => scalar keys %{$packages->[0]},
					max        => -1, #- will be updated after reading current hdlist.
					selected   => $selected, #- default value is only CD1, it is really the minimal.
				      };

    #- copy hdlist file directly to $prefix/var/lib/urpmi, this will be used
    #- for getting header of package during installation or after by urpmi.
    my $newf = "$prefix/var/lib/urpmi/hdlist.$fakemedium.cz" . ($hdlist =~ /\.cz2/ && "2");
    -e $newf and do { unlink $newf or die "cannot remove $newf: $!"; };
    install_any::getAndSaveFile($fhdlist || "Mandrake/base/$hdlist", $newf) or die "no $hdlist found";
    symlinkf $newf, "/tmp/$hdlist";

    #- extract filename from archive, this take advantage of verifying
    #- the archive too.
    open F, "packdrake $newf |";
    foreach (<F>) {
	chomp;
	/^[dlf]\s+/ or next;
	if (/^f\s+\d+\s+(.*)/) {
	    my $pkg = { file   => $1, #- rebuild filename according to header one
			flags  => 0,  #- flags
			medium => $m,
		      };
	    my $specific_arch = packageSpecificArch($pkg);
	    if (!$specific_arch || compat_arch($specific_arch)) {
		my $old_pkg = $packages->[0]{packageName($pkg)};
		if ($old_pkg) {
		    if (packageVersion($pkg) eq packageVersion($old_pkg) && packageRelease($pkg) eq packageRelease($old_pkg)) {
			if (better_arch($specific_arch, packageSpecificArch($old_pkg))) {
			    log::l("replacing old package with package $1 with better arch: $specific_arch");
			    $packages->[0]{packageName($pkg)} = $pkg;
			} else {
			    log::l("keeping old package against package $1 with worse arch");
			}
		    } else {
		        log::l("ignoring package $1 already present in distribution with different version or release");
		    }
		} else {
		    $packages->[0]{packageName($pkg)} = $pkg;
		}
	    } else {
	        log::l("ignoring package $1 with incompatible arch: $specific_arch");
	    }
	} else {
	    die "bad hdlist file: $newf";
	}
    }
    close F or die "unable to parse $newf";

    #- update maximal index.
    $m->{max} = scalar(keys %{$packages->[0]}) - 1;
    $m->{max} >= $m->{min} or die "nothing found while parsing $newf";
    log::l("read " . ($m->{max} - $m->{min} + 1) . " headers in $hdlist");
    1;
}

sub getOtherDeps($$) {
    my ($packages, $f) = @_;

    #- this version of getDeps is customized for handling errors more easily and
    #- convert reference by name to deps id including closure computation.
    foreach (<$f>) {
	my ($name, $version, $release, $size, $deps) = /^(\S*)-([^-\s]+)-([^-\s]+)\s+(\d+)\s+(.*)/;
	my $pkg = $packages->[0]{$name};

	$pkg or log::l("ignoring package $name-$version-$release in depslist is not in hdlist"), next;
	$version eq packageVersion($pkg) and $release eq packageRelease($pkg)
	  or log::l("warning package $name-$version-$release in depslist mismatch version or release in hdlist ($version ne ",
		    packageVersion($pkg), " or $release ne ", packageRelease($pkg), ")"), next;

	my $index = scalar @{$packages->[1]};
	$index >= $pkg->{medium}{min} && $index <= $pkg->{medium}{max}
	  or log::l("ignoring package $name-$version-$release in depslist outside of hdlist indexation");

	#- here we have to translate referenced deps by name to id.
	#- this include a closure on deps too.
	my %closuredeps;
	@closuredeps{map { packageId($packages, $_), packageDepsId($_) }
		       grep { $_ }
			 map { packageByName($packages, $_) or do { log::l("unknown package $_ in depslist for closure"); undef } }
			   split /\s+/, $deps} = ();

	$pkg->{sizeDeps} = join " ", $size, keys %closuredeps;

	push @{$packages->[1]}, $pkg;
    }

    #- check for same number of package in depslist and hdlists, avoid being to hard.
    scalar(keys %{$packages->[0]}) == scalar(@{$packages->[1]})
      or log::l("other depslist has not same package as hdlist file");
}

sub getDeps($) {
    my ($prefix, $packages) = @_;

    #- this is necessary for urpmi.
    install_any::getAndSaveFile('Mandrake/base/depslist.ordered', "$prefix/var/lib/urpmi/depslist.ordered");
    install_any::getAndSaveFile('Mandrake/base/provides', "$prefix/var/lib/urpmi/provides");

    #- beware of heavily mismatching depslist.ordered file against hdlist files.
    my $mismatch = 0;

    #- update dependencies list, provides attributes are updated later
    #- cross reference to be resolved on id (think of loop requires)
    #- provides should be updated after base flag has been set to save
    #- memory.
    local *F;
    open F, "$prefix/var/lib/urpmi/depslist.ordered" or die "cann't find dependancies list";
    foreach (<F>) {
	my ($name, $version, $release, $sizeDeps) = /^(\S*)-([^-\s]+)-([^-\s]+)\s+(.*)/;
	my $pkg = $packages->[0]{$name};

	$pkg or
	  log::l("ignoring $name-$version-$release in depslist is not in hdlist"), $mismatch = 1, next;
	$version eq packageVersion($pkg) and $release eq packageRelease($pkg) or
	  log::l("ignoring $name-$version-$release in depslist mismatch version or release in hdlist ($version ne ", packageVersion($pkg), " or $release ne ", packageRelease($pkg), ")"), $mismatch = 1, next;

	$pkg->{sizeDeps} = $sizeDeps;

	#- check position of package in depslist according to precomputed
	#- limit by hdlist, very strict :-)
	#- above warning have chance to raise an exception here, but may help
	#- for debugging.
	my $i = scalar @{$packages->[1]};
	$i >= $pkg->{medium}{min} && $i <= $pkg->{medium}{max} or $mismatch = 1;

	#- package are already sorted in depslist to enable small transaction and multiple medium.
	push @{$packages->[1]}, $pkg;
    }

    #- check for mismatching package, it should breaj with above die unless depslist has too many errors!
    $mismatch and die "depslist.ordered mismatch against hdlist files";

    #- check for same number of package in depslist and hdlists.
    scalar(keys %{$packages->[0]}) == scalar(@{$packages->[1]}) or die "depslist.ordered has not same package as hdlist files";
}

sub getProvides($) {
    my ($packages) = @_;

    #- update provides according to dependencies, here are stored
    #- reference to package directly and choice are included, this
    #- assume only 1 of the choice is selected, else on unselection
    #- the provided package will be deleted where other package still
    #- need it.
    #- base package are not updated because they cannot be unselected,
    #- this save certainly a lot of memory since most of them may be
    #- needed by a large number of package.

    foreach my $pkg (@{$packages->[1]}) {
	packageFlagBase($pkg) and next;
	map { my $provided = $packages->[1][$_] or die "invalid package index $_";
	      packageFlagBase($provided) or push @{$provided->{provides} ||= []}, $pkg;
	  } map { split '\|' } grep { !/^NOTFOUND_/ } packageDepsId($pkg);
    }
}

sub readCompss {
    my ($prefix, $packages) = @_;
    my ($p, @compss);

    #- this is necessary for urpmi.
    install_any::getAndSaveFile('Mandrake/base/compss', "$prefix/var/lib/urpmi/compss");

    local *F;
    open F, "$prefix/var/lib/urpmi/compss" or die "can't find compss";
    foreach (<F>) {
	/^\s*$/ || /^#/ and next;
	s/#.*//;

	if (/^(\S.*)/) {
	    $p = $1;
	} else {
	    /(\S+)/;
	    $packages->[0]{$1} or log::l("unknown package $1 in compss"), next;
	    push @compss, "$p/$1";
	}
    }
    \@compss;
}

sub readCompssList {
    my ($packages, $langs) = @_;
    my $f = install_any::getFile('Mandrake/base/compssList') or die "can't find compssList";
    my @levels = split ' ', <$f>;

    foreach (<$f>) {
	/^\s*$/ || /^#/ and next;
	my ($name, @values) = split;
	my $p = packageByName($packages, $name) or log::l("unknown entry $name (in compssList)"), next;
	$p->{values} = \@values;
    }

    my %done;
    foreach (@$langs) {
	my $p = packageByName($packages, "locales-$_") or next;
	foreach ($p, @{$p->{provides} || []}, map { packageByName($packages, $_) } @{$by_lang{$_} || []}) {
	    next if !$_ || $done{$_}; $done{$_} = 1;
	    $_->{values} = [ map { $_ + 90 } @{$_->{values} || [ (0) x @levels ]} ];
	}
    }
    my $l = { map_index { $_ => $::i } @levels };
}

sub readCompssUsers {
    my ($packages, $compss, $meta_class) = @_;
    my (%compssUsers, %compssUsersIcons, , %compssUsersDescr, @sorted, $l);
    my (%compss); 
    foreach (@$compss) {
	local ($_, $a) = m|(.*)/(.*)|;
	do { push @{$compss{$_}}, $a } while s|/[^/]+||;
    }

    my $map = sub {
	$l or return;
	$_ = $packages->[0]{$_} or log::l("unknown package $_ (in compssUsers)") foreach @$l;
    };
    my $file = 'Mandrake/base/compssUsers';
    my $f = install_any::getFile("$file.$meta_class") || install_any::getFile($file) or die "can't find $file";
    foreach (<$f>) {
	/^\s*$/ || /^#/ and next;
	s/#.*//;

	if (/^(\S.*)/) {
	    &$map;
	    my ($icon, $descr);
	    /^(.*?)\s*\[icon=(.*?)\](.*)/  and $_ = "$1$3", $icon  = $2;
	    /^(.*?)\s*\[descr=(.*?)\](.*)/ and $_ = "$1$3", $descr = $2;
	    $compssUsersIcons{$_} = $icon; 
	    $compssUsersDescr{$_} = $descr; 
	    push @sorted, $_;
	    $compssUsers{$_} = $l = [];